What I Did
First I accept that I am lacking in spring security knowledge.
I am trying secure rest services for one of our product. I am using spring security OAuth2 JWT. I want to allow anonymous as well as registered users to access my resources.
Suppose I have one service "http://localhost:8282/melayer/articles" and when I run following command
(1). curl -X POST -vu melayer:12345 http://localhost:8282/melayer/oauth/token -H "Accept: application/json" -d "password=melayer&username=melayer&grant_type=password&scope=write&client_secret=12345&client_id=melayer"
I am able to receive access_token, refresh_token etc. Everything works fantastic, even I can access url http://localhost:8282/melayer/articles with received acces_token
(2). curl http://localhost:8282/melayer/articles -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0NjA3NzY5NDIsInVzZXJfbmFtZSI6ImVjb2tyeXB0IiwianRpIjoiNWI5ZmE4NjYtMTBlNS00NDA2LTgxYmMtYjM3NWVmNGE0ZmQ1IiwiY2xpZW50X2lkIjoiZWNva3J5cHQiLCJzY29wZSI6WyJ3cml0ZSJdfQ.4jO9euBz4TSSNh7M3l2YBD1QPblE0ZyOfGm4VtyFMFY"
What I want to understand
I want to receive access_token anonymously i.e. I dont want to pass user name, password or client secret, I want to run curl command in following way
curl -X POST http://localhost:8282/melayer/oauth/token -H "Accept: application/json"
My one of the concern is, I want access_token with or without user credentials I am trying to achieve this from last week, Am I missing something ? is it possible ? what is correct way to do this ?
It is kind request to help me on this :)
If anyone want to see my code please refer Git repo https://github.com/aniruddhha/spring-security-oauth2-jwt
I think you Misunderstood the access token concept, access tokens are meant to be used on behalf of authenticated user.
OAuth2 supports different grants types (password, authorization_code, etc) , check the spec Oauth2 Spec
In order to authenticate used you can use any one of those grants or could create your own (eg: login with Google token ) but you must send some form of user credentials to identify the user and the client credentials to identify the client.
Access token cannot be used as some kind of ApiKey used to access public api
Related
I have an existing spring boot application which provides Rest API's and it doen't do authentication. Authentication is being handled by FrontEnd applcation and for evert API request from FrontEnd, we receive token in the Request Headers(authorization) and we validate this token by calling below 2 service provider endpoints using org.springframework.web.client.RestTemplate before proceed with the API requests. For this we have written an interceptor to intercept every request and validate the token.
Token Info end point to validate token and User Info endpoint to get User Details.
UserInfo: https://dev-login.iam.organisation.com/organisationsso/oauth2/userinfo
TokenInfo: https://dev-login.iam.organisation.com/organisationsso/oauth2/tokeninfo?access_token=
User Info Sample request:
curl -X GET \
https://dev-login.iam.organisation.com/organisationsso/oauth2/userinfo \
-H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJub25jZSI6Il…' \
-H 'cache-control: no-cache'
Token Info Sample request:
curl -X GET \
'https://dev-login.iam.organisation.com/organisationsso/oauth2/tokeninfo?access_token=eyJ0eXAiOiJKV1QiLCJub25jZSI6Il..' \
-H 'Cache-Control: no-cache'
Now we are changing the IAM service provider to Azure Active Directory B2C and I don't have much idea on how to validate tokeninfo and userinfo with Azure AD using existing org.springframework.web.client.RestTemplate or different approach.
I have found docs for userinfo and it seems we can use RestTemplate to call the endpoint to get the user information but could not find the Rest Template approach for Token info.
Can someone guide me to the correct and simple approach to avoid the multiple changes in the existing code.
ACCESS TOKENS
For access tokens you will use JWT validation in memory - here is a Spring Boot API Example.
USER INFO
To get user info in an API is tricky - not sure if you need to do that? If so you may need to get a different (graph) token using the On Behalf Of Flow.
RESOURCES OF MINE
I remember struggling with some of this a couple of years ago, so my links below may provide a useful hint or two:
Code
Blog Post
I used this curl command to retrieve session details for a user in keycloak:
curl -X GET \
-H 'Authorization: Bearer $TOKEN' \
http://192.168.X.X:8080/auth/admin/realms/$REALM_NAME/users/$ID_OF_CLIENT/sessions
and in response we have:
[{
"id":"194d6b10-5b94-42c3-86d8-4d1780f70f52",
"username":"admin",
"userId":"e258f775-3597-4a72-a490-7bgd7c1cdfdb",
"ipAddress":"192.168.X.X",
"start":1589006511000,
"lastAccess":1589007060000,
"clients" :
{
"53d98bf8-fffd-484c-aae8-500a7cf7a8b6":"authz-servlet",
"9bc56128-972e-41fe-8946-3ce4b5660e24":"authz-client-app3"
}
}]
now I need to add some more details in the session information such as browser version for the logged-in user. Is there any way to add these details?
I suggest you to take a look at userinfo OIDC endpoint. Comparing to you current approach (utilizing Admin REST Api with administrative token) it accepts token issued for end user. If it ok for you, you will be able to customize endpoint output as you want. Customization available at Client Scopes and Mappers tabs in client settings.
Set of mappers available by default is quite wide but
i'm afraid by default Keycloak is not preserve information about UA, so you have to develop your own logic to extract it during login flow and than to store it in user session. If you are not familiar with implementing Keycloak Java SPI you can try to do implement your logic via JS mapper.
https://www.keycloak.org/docs/latest/server_admin/index.html#_protocol-mappers_oidc-user-session-note-mappers
https://www.keycloak.org/docs/latest/server_development/#_script_providers
AFAIK some examples should be in keycloak github
I want to use Bitbucket's Rest API with Bitbucket's two-factor authentication enabled, so I can administer my account using curl via the terminal. Previously, I made REST API calls without 2FA and now I want to make this transition.
With 2FA enabled, you need to use the OAuth 2.0 protocol to make API calls; rather than the standard REST API invocations you'll find on the Bitbucket site.
Now, I got as far as creating a so-called consumer, on the Bitbucket website. This generates a Key and a Secret.
The part where I got stuck is in the following. With this Key and Secret, you can obtain a so-called access token (which expires after an hour) via
https://bitbucket.org/site/oauth2/authorize?client_id={client_id}&response_type=code
, which you can do via a the curl command
$ curl -X POST -u "client_id:secret" \
https://bitbucket.org/site/oauth2/access_token \
-d grant_type=authorization_code -d code={code}.
I don't know how to obtain this access token; i.e., the step from invoking the curl command to having it in a Bash variable.
Once we've obtained our access token we can make API requests by including it in our curl command, according to the Bitbucket documentation. I presume, something like,
curl -u "client_id:secret" https://api.bitbucket.org/2.0/[API Request] --data-urlencode "access_token=$[Access_token]" --data "[api_request_data]=[Api_request_data]"
, where $[Access_token] is our Bash variable holding our unexpired access token.
I want to create two functions implemented in Bash: one to obtain an access token; and, one to refresh the access token. Or is there a more simple way?
Anyhow, a quick outline on how to make REST API calls with 2FA enabled, would be highly appreciated.
You can use a Bitbucket "app password". More info here.
I connecting the google spreadsheet API. I have already granted permission to the user and retrieved the code. I would like to refresh the token with the refresh token, but cannot find the url. can anyone point me to the url needed? I cannot use the libraries since I am using an ETL tool and not a code to connect to the service.
Thank you
Nir
This worked for me:
curl https://www.googleapis.com/oauth2/v4/token \
-d client_id=$CLIENT_ID \
-d client_secret=$CLIENT_SECRET \
-d refresh_token=$REFRESH_TOKEN \
-d grant_type=refresh_token
For the first authorization code exchange, a refresh token is obtained in offline scenarios. In these cases, your application may obtain a new access token by sending a refresh token to the Google OAuth 2.0 Authorization server.
As discussed in the documentation, to obtain a new access token, your application sends an HTTPS POST request to https://www.googleapis.com/oauth2/v4/token.
We're using the username-password grant to obtain an access token from our auth server. We want to refresh the access token before it expires using the provided refresh token until the user logs out or closes the client app.
However I just cannot find any examples of how to issue this refresh token request..
To obtain the token we call something like:
curl -v --data "grant_type=password&username=user&password=pass&client_id=my_client" http://localhost:8080/oauth/token
So to refresh I'd expect the call to look like this:
curl -v --data "grant_type=refresh_token&access_token=THE_ACCESS_TOKEN&refresh_token=THE_REFRESH_TOKEN" http://localhost:8080/oauth/token
or maybe
curl -v -H "Authorization: Bearer THE_ACCESS_TOKEN" --data "grant_type=refresh_token&refresh_token=THE_REFRESH_TOKEN" http://localhost:8080/oauth/token
But it will just give me a 401..
Oh yeah, maybe I need to add the clientId? I cannot use the client secret, because there is none (see above request to obtain the token). Authentication is done using username and password after all..
I think we have the server configuration right, so I'll not post it here. If one of my example requests should work and you need to see the important config parts I'll add them.
Thanks!
So as I said, we don't use a client secret, because we cannot have that hanging around in the Javascript client app. And it's not needed anyway, when using the username-password grant. (See the way we request the access token).
Indeed I was close to the solution and finally figured it out:
curl -v --data "grant_type=refresh_token&client_id=THE_CLIENT_ID&refresh_token=THE_REFRESH_TOKEN" http://localhost:8080/oauth/token
so no need for the access token or the client secret.
Over all it feels safe enough.
We don't store any secret on the client app side.
The users always need a password to log in and can only see their resources.
We limit the validity of the refresh token to a realistic time like a workday or something so that even if it is compromised the window for an attacker is limited while still allowing the user to conveniently stay connected to the resource server throughout a long session.
For the password grant_type, a clientId and clientSecret are required. You were close with your third attempt, but you pass the Base64-encoded clientId and clientSecret instead of the Access Token in the Authorization header. This is the proper refresh token request:
curl -H "Authorization: Bearer [base64encode(clientId:clientSecret)]" "https://yourdomain.com/oauth/token?grant_type=refresh_token&refresh_token=[yourRefreshToken]"
For a good reference, check this out: http://techblog.hybris.com/2012/06/11/oauth2-resource-owner-password-flow/