I'm working on implementing OAuth 2.0 to a stack of apps I have to reduce the required login credentials. However I am struggeling in understanding the OpenID Connect on top of OAuth 2.0 and how I am supposed to verify the JWT token given. Should the public key be supplied inside the actual token so that the client can check the signature?
Also, correct me if I'm wrong, but I believe this token is never sent to the resource server, but acts as a "helping hand" for the client to serve correct output to the user based on information given in the token? If so, is there a set of standards on what type of information each JWT should contain?
A Identity Token is sent following a Successful Token Response which is typically a JWT.
The ID Token validation is described within Section 3.1.3.7. ID Token Validation.
For ID tokens secured with the RSA or EC signature (e.g. RS256), you need the IdP’s public JSON Web Key (JWK) set. It is published as a simple JSON document at an URL which is also advertised in the OpenID Provider’s metadata] in the jwks_uri parameter. You can check out Google’s JSON Web Key (JWK) to see what such as JWK set looks like.
For ID tokens secured with an HMAC (e.g. HS256) you use the client_secret to perform the validation.
Related
There is a lot of information on OAuth, OIDC and Keycloak, but the main thing every tutorial seems to gloss over is offline validation. The only information I found is in the Keycloak docs on RPT introspection:
No. Just like a regular access token issued by a Keycloak server, RPTs also use the JSON web token (JWT) specification as the default format. If you want to validate these tokens without a call to the remote introspection endpoint, you can decode the RPT and query for its validity locally. Once you decode the token, you can also use the permissions within the token to enforce authorization decisions.
If I wanted to verify a user's request with an authorization token, I would make a request to the Keycloak introspection (or userinfo?) API. I'm not completely sure, but I would guess that Keycloak then verifies the info encoded in the JWT with the Keycloak user database.
However, what if I don't want to make a Keycloak request on every API request? This could improve system performance by limiting the amount of HTTP requests. There are mentions of JWT signature validations and reading the scope and user information encoded in the JWT, but I don't see how this guarantees safety. Isn't it possible to just generate any old JWT, encode any information you want and basically spoof an authorization token? How would I check if the user mentioned in the JWT really exists in the Keycloak database?
I think I am missing some crucial part of this technology.
For example, in ASP.NET Core, an API that receives a JWT token will, at startup, download the public signing keys from the token provider, and by default, it will refresh the keys every 24 hours.
So, when the API receives a JWT token, it will do various checks to validate the token, including:
Validating the signature using the provider public signing key
Validate the audience claim (is the token intended for me?)
Validate the expiry date
The API should not need to query anything against the token provider (keycloak) to let the user in.
However, then we have authorization (What the user is allowed to do), which is a different thing, and that all depends on your requirements.
JWT is all about who the user is; if the token is valid, you can trust that information.
With JWT-tokens, your API can work almost offline from the token provider. It can even be 100% disconnected if you copy the public signing key manually into the API.
I am pretty new with these protocols, and I am having some trouble understanding something.
I am currently working on an application which API and Frontend is mine, I use azure identity platform to receive the tokens on the clientside and send the token to the server that validates the token using passport-azure-ad bearerStrategy. (I have my app registration for that purposes ofcourse).
The thing that I don't get, is that I missed correctly used the tokens I received from azure in my client and sent the ID Token to my API, it verifes it as a valid one and user is authenticated to perform the request sent.
But, as I read here https://learn.microsoft.com/en-us/azure/active-directory/develop/id-tokens, and in any other article about oAuth2 and openID, ID tokens are for UX stuff and client, while I should have used the access token in my request to my API.
But howcome the ID Token is also verified in my API? It makes no sense for me, or am I missing something?
And if so, is there any vurlnabilty in using Id Token as I did?
Thank you!
APIs should first validate the JWT access token, to check these fields have allowed values. An ID token will then fail the audience check.
JWT signature
Not expired / valid at this time
Issuer (a Microsoft ID)
Audience (eg api.mycompany.com)
Access tokens have scopes, whereas ID tokens do not. Every API endpoint should validate the received scope, eg to ensure that it has received the right type of token. This will also ensure that the API does not accept ID tokens.
So although some API tech stacks accept ID tokens, making the standard checks will ensure the right behavior. And the real API authorization is then done using claims, to apply your business rules.
I write a rest api with yii2 and i am using oAuth2 , the problem is when user want login , client web application should send request to get token , request should contain client_id and secret_key and username and password in this case user can simply inspect element and click to network and see posted parameter to the server this means user can see client_id and secret_key.
client_id and secret_key are signature for each application and server can find out witch application use api.
how to handle this security issue?
It seems you have missed out one key element of OAuth 2.0, client type.
OAuth 2.0 defines two types of clients, public clients and confidentiatl clients.
2.1. Client Types
confidential
These are the clients which can protect a credential. They have the
full potential to use authorization code grant type, which obtain
token from backchannel request. Because they use backchannel to obtain
tokens, their credentials are never exposed to end user(via user
agent)
public
Clients which cannot protect credentials. For example SPA clients and
mobile apps comes to this category.
In your case, you seems to have a public client (user agent based application in broswer as it seems). In such case, you should set your client type to a public client. If this is not the case, you are not utilizing a proper back channel call from your web application.
Additionally, public clients which use authorization code flow can use PKCE to avoid authorization code theft attacks. Related RFC can be found from RFC7636
If an authentication server supplies multiple JSON Web Keys (e.g. https://www.googleapis.com/oauth2/v3/certs) which should be used to verify an OpenID Connect id_token as part of the OPenID Connect Implicit Flow?
Should the id_token be verified with the first JSON Web Key, all of the JSON Web Keys, or is the id_token considered valid if it can be verified with any of these provided JSON Web Keys?
Thanks!
When there are multiple keys in play that the OpenID Connect provider could use to sign an id_token, the header of the id_token would typically contain a key identifier (in the kid element) of the key that is actually used. That corresponds to the kid element in the JWK published on the (jwks_uri) endpoint that you describe. So the id_token would only be valid if it can be verified using the key that is associated with the kid in the header.
I'm trying to implement the Resource Owner & Password Credentials flow from the OAuth 2 spec. I'm having trouble understanding the token_type value that gets sent back with a valid response. In the spec all the examples show "token_type":"example" but says it should be
token_type
REQUIRED. The type of the token issued as described in
Section 7.1. Value is case insensitive.
Can someone please explain this to me?
token_type is a parameter in Access Token generate call to Authorization server, which essentially represents how an access_token will be generated and presented for resource access calls.
You provide token_type in the access token generation call to an authorization server.
If you choose Bearer (default on most implementation), an access_token is generated and sent back to you. Bearer can be simply understood as "give access to the bearer of this token." One valid token and no question asked. On the other hand, if you choose Mac and sign_type (default hmac-sha-1 on most implementation), the access token is generated and kept as secret in Key Manager as an attribute, and an encrypted secret is sent back as access_token.
Yes, you can use your own implementation of token_type, but that might not make much sense as developers will need to follow your process rather than standard implementations of OAuth.
Anyone can define "token_type" as an OAuth 2.0 extension, but currently "bearer" token type is the most common one.
https://www.rfc-editor.org/rfc/rfc6750
Basically that's what Facebook is using. Their implementation is a bit behind from the latest spec though.
If you want to be more secure than Facebook (or as secure as OAuth 1.0 which has "signature"), you can use "mac" token type.
However, it will be hard way since the mac spec is still changing rapidly.
https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-http-mac-05
From RFC 6750, Section 1.2:
Bearer Token
A security token with the property that any party in possession of the token (a "bearer") can use the token in any way that any other party in possession of it can. Using a bearer token does not require a bearer to prove possession of cryptographic key material (proof-of-possession).
The Bearer Token or Refresh token is created for you by the Authentication server. When a user authenticates your application (client) the authentication server then goes and generates for your a Bearer Token (refresh token) which you can then use to get an access token.
The Bearer Token is normally some kind of cryptic value created by the authentication server, it isn't random it is created based upon the user giving you access and the client your application getting access.
See also: Mozilla MDN Header Information.