Should I verify issuer and audience?
If I verify only an issuer, the sender could be someone who is authorized to another apps? If I verify only an audience, the sender could be someone who is authorized the same name app but issued by a different issuer (that means a different app)?
You should validate both if both are present.
You should always verify the issuer attribute is what you expect. The two uses of the issuer field in the token are to provide a namespace for the user identity claim and a reference to the right verification key if you accept multiple issuers as valid for your service. So in some circumstances (one issuer trusted and the signature checks out) you might feel you don't technically need to read the issuer field. But it is part of the signed data, and you know what it should be, so validating it is better from a cryptographic security standpoint.
If the audience is given in the token, you should respect it. If the issuer intends you to only use the identity for a specific service, and you aren't that service, then something is wrong with the application or the user's intent. In that circumstance, you are much better off not accepting the token. But if the audience is not provided and you trust the issuer, it shouldn't be a problem to accept the token.
Related
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.
Sounds like stupid question, But i cannot find/infer answer of following question from many articles.
Who is Issuer? (probably the token provider we trust. Like "Google, Faceboock, etc" and our site accepts tokens from theme).
Who is Audience?
Should i validate these two if i don't use OAuth and OpenID? I mean, Are they only used for 3rd-party authentication/authorization (because my site is the only issuer of my own tokens)?
What risk should i take if i don't validate these two, when my site don't use 3rd-parties to authenticate and authorize?
yes, the issuer is the Provider of the token
the Client i.e. the recipient in OpenID Connect, the Resource Server in OAuth 2.0
if a JWT has an audience, the recipient should validate that it is the audience
someone uses a token that was issued for a different service/API (e.g. API B) against your service/API (e.g. API A)
I am implementing OAuth 2.0 with JWT in my application and am having trouble deciding what to set as my aud claim as. A user will "login" to my client via my authentication server to gain access to my API (resource) server. I want my tokens to only be valid for use with a specific client and specific API.
When logging in from my client, I include it't client_id in the request, but in most implementations I've found, the aud is set to that client_id. I'm leaning towards including a customer audience_id field in my login request and then setting the aud in the token to an array of the client_id and the audience_id, but that feels like it just means that that token is valid for both those audiences, which makes me think I should just add a custom claim called client to specifically state that this token was created for a specific client.
I have not come across any implementations online that include both a client_id and audience_id(s) in an OAuth login request, nor do I see a reserved claim for client in the spec.
Am I missing something here?
What is best practice for specifically stating a different client_id and audience_id in a JWT?
The audience of the JWT is the Resource Server as that is where the token will be processed, i.e. verified, inspected and acted upon. From RFC 7519, https://www.rfc-editor.org/rfc/rfc7519#section-4.1.3:
The "aud" (audience) claim identifies the recipients that the JWT is
intended for. Each principal intended to process the JWT MUST
identify itself with a value in the audience claim.
[...]
The interpretation of audience values is generally application specific.
[...]
So best practice is that aud should identify the Resource Server.
The Client is only the presenter of the token and it is best practice (i.e. in OpenID Connect and some emerging OAuth 2.0 exension drafts) to use the azp (Authorized Presenter) for that claim. From http://openid.net/specs/openid-connect-core-1_0.html#CodeIDToken :
azp
OPTIONAL. Authorized party - the party to which the ID Token was
issued. If present, it MUST contain the OAuth 2.0 Client ID of this
party. This Claim is only needed when the ID Token has a single
audience value and that audience is different than the authorized
party.
[...]
So best practice is that azp identifies the Client.
I'm working on implementing OAuth 2.0 JWT access_token in my authentication server. But, I'm not clear on what the differences are between the JWT aud claim and the client_id HTTP header value. Are they the same? If not, can you explain the difference between the two?
My suspicion is that aud should refer to the resource server(s), and the client_id should refer to one of the client applications recognized by the authentication server (i.e. web app, or iOS app).
In my current case, my resource server is also my web app client.
As it turns out, my suspicions were right. The audience aud claim in a JWT is meant to refer to the Resource Servers that should accept the token.
As this post simply puts it:
The audience of a token is the intended recipient of the token.
The audience value is a string -- typically, the base address of the
resource being accessed, such as https://contoso.com.
The client_id in OAuth refers to the client application that will be requesting resources from the Resource Server.
The Client app (e.g. your iOS app) will request a JWT from your Authentication Server. In doing so, it passes it's client_id and client_secret along with any user credentials that may be required. The Authorization Server validates the client using the client_id and client_secret and returns a JWT.
The JWT will contain an aud claim that specifies which Resource Servers the JWT is valid for. If the aud contains www.myfunwebapp.com, but the client app tries to use the JWT on www.supersecretwebapp.com, then access will be denied because that Resource Server will see that the JWT was not meant for it.
The JWT aud (Audience) Claim
According to RFC 7519:
The "aud" (audience) claim identifies the recipients that the JWT is
intended for. Each principal intended to process the JWT MUST
identify itself with a value in the audience claim. If the principal
processing the claim does not identify itself with a value in the
"aud" claim when this claim is present, then the JWT MUST be
rejected. In the general case, the "aud" value is an array of case-
sensitive strings, each containing a StringOrURI value. In the
special case when the JWT has one audience, the "aud" value MAY be a
single case-sensitive string containing a StringOrURI value. The
interpretation of audience values is generally application specific.
Use of this claim is OPTIONAL.
The Audience (aud) claim as defined by the spec is generic, and is application specific. The intended use is to identify intended recipients of the token. What a recipient means is application specific. An audience value is either a list of strings, or it can be a single string if there is only one aud claim. The creator of the token does not enforce that aud is validated correctly, the responsibility is the recipient's to determine whether the token should be used.
Whatever the value is, when a recipient is validating the JWT and it wishes to validate that the token was intended to be used for its purposes, it MUST determine what value in aud identifies itself, and the token should only validate if the recipient's declared ID is present in the aud claim. It does not matter if this is a URL or some other application specific string. For example, if my system decides to identify itself in aud with the string: api3.app.com, then it should only accept the JWT if the aud claim contains api3.app.com in its list of audience values.
Of course, recipients may choose to disregard aud, so this is only useful if a recipient would like positive validation that the token was created for it specifically.
My interpretation based on the specification is that the aud claim is useful to create purpose-built JWTs that are only valid for certain purposes. For one system, this may mean you would like a token to be valid for some features but not for others. You could issue tokens that are restricted to only a certain "audience", while still using the same keys and validation algorithm.
Since in the typical case a JWT is generated by a trusted service, and used by other trusted systems (systems which do not want to use invalid tokens), these systems simply need to coordinate the values they will be using.
Of course, aud is completely optional and can be ignored if your use case doesn't warrant it. If you don't want to restrict tokens to being used by specific audiences, or none of your systems actually will validate the aud token, then it is useless.
Example: Access vs. Refresh Tokens
One contrived (yet simple) example I can think of is perhaps we want to use JWTs for access and refresh tokens without having to implement separate encryption keys and algorithms, but simply want to ensure that access tokens will not validate as refresh tokens, or vice-versa.
By using aud, we can specify a claim of refresh for refresh tokens and a claim of access for access tokens upon creating these tokens. When a request is made to get a new access token from a refresh token, we need to validate that the refresh token was a genuine refresh token. The aud validation as described above will tell us whether the token was actually a valid refresh token by looking specifically for a claim of refresh in aud.
OAuth Client ID vs. JWT aud Claim
The OAuth Client ID is completely unrelated, and has no direct correlation to JWT aud claims. From the perspective of OAuth, the tokens are opaque objects.
The application which accepts these tokens is responsible for parsing and validating the meaning of these tokens. I don't see much value in specifying OAuth Client ID within a JWT aud claim.
If you came here searching OpenID Connect (OIDC): OAuth 2.0 != OIDC
I recognize that this is tagged for oauth 2.0 and NOT OIDC, however there is frequently a conflation between the 2 standards since both standards can use JWTs and the aud claim. And one (OIDC) is basically an extension of the other (OAUTH 2.0). (I stumbled across this question looking for OIDC myself.)
OAuth 2.0 Access Tokens##
For OAuth 2.0 Access tokens, existing answers pretty well cover it. Additionally here is one relevant section from OAuth 2.0 Framework (RFC 6749)
For public clients using implicit flows, this specification does not
provide any method for the client to determine what client an access
token was issued to.
...
Authenticating resource owners to clients is out of scope for this
specification. Any specification that uses the authorization process
as a form of delegated end-user authentication to the client (e.g.,
third-party sign-in service) MUST NOT use the implicit flow without
additional security mechanisms that would enable the client to
determine if the access token was issued for its use (e.g., audience-
restricting the access token).
OIDC ID Tokens##
OIDC has ID Tokens in addition to Access tokens. The OIDC spec is explicit on the use of the aud claim in ID Tokens. (openid-connect-core-1.0)
aud
REQUIRED. Audience(s) that this ID Token is intended for. It MUST contain the OAuth 2.0 client_id of the Relying Party as an audience value. It MAY also contain identifiers for other audiences. In the general case, the aud value is an array of case sensitive strings. In the common special case when there is one audience, the aud value MAY be a single case sensitive string.
furthermore OIDC specifies the azp claim that is used in conjunction with aud when aud has more than one value.
azp
OPTIONAL. Authorized party - the party to which the ID Token was issued. If present, it MUST contain the OAuth 2.0 Client ID of this party. This Claim is only needed when the ID Token has a single audience value and that audience is different than the authorized party. It MAY be included even when the authorized party is the same as the sole audience. The azp value is a case sensitive string containing a StringOrURI value.
Though this is old, I think question is valid even today
My suspicion is that aud should refer to the resource server(s), and
the client_id should refer to one of the client applications
recognized by the authentication server
Yes, aud should refer to token consuming party. And client_id refers to token obtaining party.
In my current case, my resource server is also my web app client.
In the OP's scenario, web app and resource server both belongs to same party. So this means client and audience to be same. But there can be situations where this is not the case.
Think about a SPA which consume an OAuth protected resource. In this scenario SPA is the client. Protected resource is the audience of access token.
This second scenario is interesting. RFC8707 "Resource Indicators for OAuth 2.0" explains where you can define the intended audience in your authorization request using resource parameter. So the resulting token will restricted to the specified audience. Also, Azure OIDC use a similar approach where it allows resource registration and allow auth request to contain resource parameter to define access token intended audience. Such mechanisms allow OAuth adpotations to have a separation between client and token consuming (audience) party.
I want to validate a SessionSecurityToken issued by a STS. By validate, I mean certify that the token is not crafted and verity that the token is issued from the STS.
Conceptually, I know that if the STS encrypt (or sign) the token with it's private key, I could decrypt (or validate signature) with a public key.
From what I understand, the STS I am using (ThinkTecture Identity Server) uses a Symmetric Signing Key to sign to token.
The SessionSecurityToken I received contains a SecurityKeys property. What represent this SecurityKeys? MSDN documentation tells: "Gets the keys associated with this session. This is usually a single key."
Is it the SymmetricKey used by my STS? If so, it means that the symmetric key is not well protected, and if anybody gets this key, he could fake a token.
Is it the token signature? If so, how can I validate the signature (assuming that I have the symmetric key)?
Any other useful information to help me understand the way we validate a SessionSecurityToken?
So first of all - STSes don't issue a session token. They issue (i guess you use WS-Fed) a SAML token. This token is signed with an X.509 certificate.
The relying party then takes the incoming SAML token and turns it into a session token and writes that to a cookie.
So why do you want to validate that? This is done automatically by the SAM.