Is there any way that when the OAuth client get the JWT token from identity server is OK or not?
I afraid the when user get the access_token and try to use base64 to decode it then users can modify the token string .
My scenario is :
I have two web portal A and B both of them integrated the Thinktecture identity server.
User A just can access portal A with "role:portalA" claim but couldn't access portal B
if user A try to login portal A and get the access_token then user A add the "role:portalB" into the the access_token then encode with base64 again.
then the modified access_token pass to the Portal B, I afraid that user A could access portal B. so I have to check the access_token to Identity server again. is that any way to validate this access_token ? or this situation will not be happened?
I believe Thinktecture Identity Server has an endpoint for this at (baseurl + "/core/accessTokenValidation?token=" + access_token).
example:
GET request to: http://localhost:3333/core/accessTokenValidation?token=aEdhoi23hlv2khdf2lkhfv4pv....
If the access_token is valid, it should return a 200 response, otherwise it'll return a JSON error message {"error":"invalid_token"} and a 4XX response.
You should wire up a call to this service to validate tokens, then cache the response.
Take a look at the source code: https://github.com/IdentityServer/IdentityServer3/blob/master/source/Core/Endpoints/Connect/AccessTokenValidationController.cs
Thinktecture IdentityServer3 has different endpoint.
More details in official documentation:
https://identityserver.github.io/Documentation/docs/endpoints/accessTokenValidation.html
Example:
GET /connect/accesstokenvalidation?token=<token>
A successful response will return a status code of 200 and the associated claims for the token.
An unsuccessful response will return a 400 with an error message.
Related
GET /realms/[REALM_NAME]/protocol/openid-connect/logout?post_logout_redirect_uri=[...]&id_token_hint=[..very large jwt-token >4096..]
Response 414 (Uri to long (link)
Keycloak version: v20.0.1
Expected: Successful logout redirect. The above request should response 302.
AFAIK, you should pass an ID token to the id_token_hint and not and access token. From the OpenID Connect standard (section 2.RP-Initiated Logout) one can read:
This specification defines the following parameters that are used in
the logout request at the Logout Endpoint:
id_token_hint RECOMMENDED. ID Token previously issued by the OP to the
RP passed to the Logout Endpoint as a hint about the End-User's
current authenticated session with the Client. This is used as an
indication of the identity of the End-User that the RP is requesting
be logged out by the OP.
So you need to pass id_token_hint=<id_token>. You get the ID token by calling the token endpoint with the scope=openid. For example, when a user logs in via browser if you request includes the scope=openid you will get (along with the refresh and access tokens) the user ID token.
It seems that the logout URI path is to long. The default length of the keycloak quarkus service is 4096 bytes (link).
this occur when Your id_token_hint is to large
Set higher length for quarkus parameter quarkus.http.limits.max-initial-line-length ...
as java parameter -quarkus.http.limits.max-initial-line-length=8192
or environment variable QUARKUS_HTTP_LIMITS_MAX_INITIAL_LINE_LENGTH=8192
I would like to know how does a Keycloak client validate the token, other than checking the signature.
I mean if a user has issued a logout request to the OID '/logout' endpoint, the token signature verification would still pass, so if the token has been invalidated by a logout, the client has to go to the KC server. So my question is, does the client go to Keycloak to check that the token is still valid, for every request that my app receives?
In OIDC normally the token is not actively checked by sending it to the keycloak server everytime. Instead the token is only checked locally (by signature verfication with the servers public key).
So you are right, a logout is not immediately recognized by a client.
Because of that you often have a flow where you distinguish between a refresh and access token. The access_token has a really short lifetime (<= 5 minutes), is used to authenticate the user and checked via signature validation.
When the access_token is not valid anymore the client need to use the refresh_token to actively obtain a new access_token from keycloak. In this step keycloak will check if the user is still logged-in before issuing the new token.
Because of that the refresh_token can have a much longer lifetime and it's not always necessary for the user to enter his credentials again.
In my REST API, user will log in with their username and password for the first time.
When they logged in successfully, we will response with the following format.
{
"token": "0c7f8b870675bc61d92baeef1e274c2d31343736393530373230",
"expire_on": "2016-11-19T18:05:20+0000",
"user_id": 30,
"user": {...}
}
On the subsequent to the REST API, we will just send token in the header to verify the user. token is 52 letters long.
Is it secure enough?
Should I send both token and user_id to verify to secure more?
It depends on how do you generate your token.
If someone can guess how they are generated then it can create a fake one.
If this is a random string that is saved on your server and for each request you check the existence in your server then you are safe.
The best current solution for stateless token is JWT. Take a look at https://jwt.io/
Did you implement your authentication layer? I would suggest having a look at the Oauth2 specification and you are interested in the section when the grant_type is password. If you follow it, it will be safe to return just the access token:
5.1. Successful Response
The authorization server issues an access token and optional
refresh token, and constructs the response by adding the following
parameters to the entity-body of the HTTP response with a 200 (OK)
status code:
access_token
REQUIRED. The access token issued by the authorization server.
token_type
REQUIRED. The type of the token issued as described in
Section 7.1. Value is case insensitive.
expires_in
RECOMMENDED. The lifetime in seconds of the access token. For
example, the value "3600" denotes that the access token will
expire in one hour from the time the response was generated.
If omitted, the authorization server SHOULD provide the
expiration time via other means or document the default value
.
I receive two JWTs: an OpenID Connect ID token (id_token) and an Access Token (access_token). The situation with OpenID is more or less clear - I can validate it using a JWKS Endpoint: https://smth.com/JWKS.
as in example (https://bitbucket.org/b_c/jose4j/wiki/JWT%20Examples):
HttpsJwks httpsJkws = new HttpsJwks("https://smth.com/JWKS");
HttpsJwksVerificationKeyResolver httpsJwksKeyResolver = new HttpsJwksVerificationKeyResolver(httpsJkws);
jwtConsumer = new JwtConsumerBuilder()
.setVerificationKeyResolver(httpsJwksKeyResolver)
.setExpectedAudience(...)
.setExpectedIssuer(...)
.build();
The question is how to proceed with the Access Token. I can extract from it the userId and userDetails, but I guess I need also to validate it?
If I try to validate the Access Token the same as for the ID Token, I am getting this error:
UnresolvableKeyException: Unable to find a suitable verification key for JWS w/ header {"alg" : "RS256", "kid":"1"}
And indeed there is no key for "kid" : "1", Also this value "1" seems kind of strange?
Am I doing something totally wrong?
It sounds like you are implementing the role of OpenID Connect client or Relying Party. The two tokens, ID token and access token, serve different purposes and should be handled differently by the client. The ID token is intended for the client and enables authentication of the end-user at the client. The client must validate the ID token (verify the signature and validate claims like exp and aud, etc.) before allowing the end-user in. The access token, however, is for the client to use to access resources or APIs but is not directly intended for the client to consume or validate. The access token is opaque to the client and the client shouldn't care or know about its details. In fact, access tokens aren't always JWTs. In OpenID Connect, the access token is used to call the user info endpoint (with the HTTP header, Authorization: Bearer [access token]) to get more claims/info about the end-user.
The value of "1" for the kid is totally legal but it is referring to a key that the AS/OP and the user info endpoint know about somehow. It is not a key at the OpenID Connect JWKS endpoint. "1" isn't a key that the client needs to know about because the client isn't supposed to directly verify the access token.
I'm developing an Android app that consumes a REST service that uses OAuth protocol. In the first activity, app shows a login screen. This is the flow:
1) User puts her username and password.
2) App makes a request to REST service, providing username and password.
3) REST service check the credentials and if are correct, ask for an access_token to my OAuth2 provider server.
4) REST service answers to the app providing the access_token and the refresh_token
5) In the next requests to the REST server (to get data like people, articles...) app will provide the access_token and the refresh_token.
6) When REST service process a request, will validate the access_token (using an token info endpoint of my OAuth server).
7) If the access_token is correct and has not expired, REST service will return the data that the app were asking for.
When REST service detects that access_token has expired, asks for another with using the refresh_roken.
Now, my questions:
When REST service retrieve a new access_token after the old one expires, has the REST service send it to the app in that response?
If so, has the app check, in each request/response, if new a new access_token has been sent from the REST service?
I don't know if I'm in the right way, I'm trying to understand the flow.
Thanks.
Assuming there's no browser involved and the app (aka. Client) uses what is called the Resource Owner Password Credentials grant, the flow is:
the User (aka. Resource Owner) provides his/her username and password to the Client
the Client makes a Token Request to the Authorization Server, providing username and password
the Authorization Server checks the credentials and if they are correct, it provides an access token and optionally a refresh token to the Client in the response
in the requests to the REST server (to get data like people, articles...) the Client will provide the access token
when the REST service process a request, it will validate the access token calling the token validation endpoint of the Authorization Server or by validating the token locally (e.g. if the access token is a JWT).
if the access token is correct, has not expired and has the right permissions (aka. "scopes"), the REST service will return the data that the Client was asking for
when the Client detects that access_token has expired (e.g. because the REST server returns an error), it asks the Authorization Server for another access token using the refresh token using the so-called Refresh Token grant/flow
OAuth 2.0 flows:
An application registers with the auth provider e.g. Facebook, Google, etc with app name, website and callback/postback URL
The application receives the client id and secret from the auth provider
The application user accesses the auth provider for authentication and user approves the resource permissions
The auth provider returns the auth token with respect to the user permissions to the application
The application accesses the resource provider using the auth tokens
The resource provider returns the protected resources after validating the auth tokens to the application
Do comment if you need more understanding!