Access Token contains almost all information from Identity Token - oauth-2.0

The tokens below are returned upon initial token request with Azure AD B2C. access_token contains most information that id_token contains.
My questions are that:
1 Since access_token contains most information that id_token contains, what scenario can access_token be used in place of id_token? what scenario must id_token be used instead of access_token?
2 What are the rules regarding use of both access_token and id_token in general?
Result upon initial token request
{
"access_token": "access_token",
"token_type": "Bearer",
"expires_in": "3600",
"refresh_token": "refresh_token",
"id_token": "id_token"
}
Below is the decoded token for the respective token:
Please note that access_token contains most information from id_token, including user information.
access_token
{
"iss": "url",
"exp": 1550539339,
"nbf": 1550535739,
"aud": "audience ",
"idp": "LocalAccount",
"sub": "guid",
"name": "user#email.com",
"emails": [
"user#email.com"
],
"tfp": "B2C_1_ROPC_Auth",
"ver": "1.0",
"iat": 1550535739,
"azp": "guid"
}
id_token
{
"iss": "url",
"exp": 1550539339,
"nbf": 1550535739,
"aud": "audience ",
"idp": "LocalAccount",
"sub": "guid",
"name": "user#email.com",
"emails": [
"user#email.com"
],
"tfp": "B2C_1_ROPC_Auth",
"ver": "1.0",
"iat": 1550535739,
"auth_time": 1550535739,
"at_hash": "access_token hash"
}
Update
Further to question 1 above:
Since access_token contains most information that id_token contains, can access_token be used instead of id_token? That is, when id_token must be used instead of access_token?

I will take google as a example,
1) let say you want to implement social login where u mostly need fields like email, 'first_name', 'last_name'., these fields are mostly available in id_token. so id_token is perfect suitable for authentication.
2) later u need to fetch google contacts of the login user., In such scenarios u can't get contacts of the user in id_token. this is where access_token comes, though u won't have the contacts in access_token but all permission to fetch the contacts.

An ID token is intended for authentication. It is represented as a JSON Web Token (JWT) that contains claims about an authentication event including the identity information for a resource owner. The ID token is intended for a client application (a single-page app) and its aud (audience) claim contains the OAuth 2.0 client_id of the client application.
An access token is intended for access by clients to resources that are owned by a resource owner. It is represented as either a JWT (e.g. Azure AD B2C represents an access token as a JWT) or an opaque token. The access token is intended for a resource application (e.g. an API app) and its aud claim contains the OAuth 2.0 client_id of the resource application.

Related

Scopes vs Roles when accessing Resource Server with Keycloak as Authentication Server

I am using Keycloak as Authorization Server and setting up SPA (Public Client) that will be connecting to a REST service (Bearer-Only client / Resource Server).
As far as I understand, scopes are group of claims and claims are information about the subject (authenticated user). Scopes are passed at authentication step to the authorization server so that it will prompt the user to permit/deny access to those claims (user data / actions). In the case of third party client trying to access data from for example Facebook, scopes are permissions given by the user to the client to access user's data from Facebook. In case of Slack scope are used to allow / deny certain permissions for the third party client to perform operations on behalf of the user.
In my case where the resource server does not hold any user information but OAuth is used for authentication / authorization and will use the access token to get users group membership and possibly role to allow/deny access to the data on the resource server.
Correct me if I am wrong but scopes are used more for the user to allow third party client to access his/her information from OIDC provider, possibly get user information from the ID Token. On the other hand Roles / Groups that is set in the access token would be used to authorize the user to get data from the the resource server
For example here is the
Access Token:
{
"exp": 1612294865,
"iat": 1612294565,
"auth_time": 1612294524,
"jti": "e6c12a30-1b54-410a-81ba-ffe947dcebc9",
"iss": "http://localhost:8080/auth/realms/demo",
"aud": "rest-service",
"sub": "e49f2e27-4b47-492e-a714-2497d4f669f8",
"typ": "Bearer",
"azp": "js-console",
"nonce": "58faa6b8-a628-4b5a-8f0a-b33643812ef2",
"session_state": "2470b7b4-1587-43d5-8747-911b01398c3d",
"acr": "0",
"allowed-origins": [
"http://localhost:8000"
],
"resource_access": {
"rest-service": {
"roles": [
"user"
]
}
},
"scope": "openid email profile",
"email_verified": false,
"preferred_username": "test",
"group": [
"/my-group"
]
}
ID Token
{
"exp": 1612294865,
"iat": 1612294565,
"auth_time": 1612294524,
"jti": "c3242eb4-9047-4913-9ac6-be3b4e2b5745",
"iss": "http://localhost:8080/auth/realms/demo",
"aud": "js-console",
"sub": "e49f2e27-4b47-492e-a714-2497d4f669f8",
"typ": "ID",
"azp": "js-console",
"nonce": "58faa6b8-a628-4b5a-8f0a-b33643812ef2",
"session_state": "2470b7b4-1587-43d5-8747-911b01398c3d",
"at_hash": "5hOJUzWD9H2DOuYCEnc6fQ",
"acr": "0",
"email_verified": false,
"preferred_username": "test"
}
The audience(aud) for the ID token is set to the Client (js-console) and returns just some user information and really only needs openid scope. The access token aud is set to the rest service that will consume the access token and retrieve the roles and group information.
This is a different usage of OAuth which in this case the user doesn't need to consent to anything but will authenticate and use the access token to get information based on the group membership.
Is my understanding is correct?
Thanks!

How can you force expire a salesforce access token?

I'm building a web app and using OAuth2 to authenticate. For testing purposes, I would like to test what happens when the access token expires and the refresh token is needed to re-authenticate. Since the salesforce oauth token does not contain an "expiry date" parameter, how would i forcefully expire the salesforce access token.
This is what is returned when a token is requested.
{
"oauth_token": {
"access_token": "<access token>",
"id": "https://login.salesforce.com/id/00DG0000000imtwMAA/005G0000001CFgeIAG",
"id_token": "<id token>",
"instance_url": "https://na47.salesforce.com",
"issued_at": "1522400000",
"refresh_token": "<refresh token>",
"scope": [
"refresh_token",
"full"
],
"signature": "<signature>",
"token_type": "Bearer"
}
}
If you want to do it manually, you can go to Setup > Security Controls > Session Management, then select the session from the list and remove it. Alternatively, if you need to do it programmatically, you could query and delete these records, which are stored in the AuthSession object.
Once you've done that, your access token will be expired, and attempts to use it will produce:
[ {
"message" : "Session expired or invalid",
"errorCode" : "INVALID_SESSION_ID"
} ]
Your refresh token will still be valid though, and you can use it to request a new access token.

Refreshing tokens with GIDSignIn iOS

I am currently using google sign to authenticate users to my app, but am having problems with the id_token after it's been refreshed. I have the following variables set up. One is for the iOS client and one is for the server. This is following AWS examples. I am using AWS to access the server and therefore need to have a client id and web application id.
static let GOOGLE_CLIENT_ID = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxx7dde.apps.googleusercontent.com"
// Backend web application client ID
static let GOOGLE_WEB_APPLICATION_ID = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxx65ap.apps.googleusercontent.com"
When I first log in the application it works as expected. I get an id token back that has the following:
{
"iss": "https://accounts.google.com",
"at_h ash": "xxxxxxxxxxxxxxxxxxxxxx",
"aud": "xxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxx65ap.apps.googleusercontent.com",
"sub": "xxxxxxxxxxxxxxxxxxxxxx",
"email_verified": true,
"azp": "xxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxx7dde.apps.googleusercontent.com",
"email": "2222MyNewEmailIsHere#gmail.com",
"iat": 1475747692,
"exp": 1475751292
}
You can see that the "aud" matches the GOOGLE_WEB_APPLICATION_ID and the "azp" matches GOOGLE_CLIENT_ID.
However if I do a refreshTokensWithHandler like so:
GIDSignIn.sharedInstance().currentUser.authentication.refreshTokensWithHandler { (GIDAuthentication, error) in
self.googleAuth = GIDAuthentication;
self.completeGoogleLogin()
}
I get a problem with the response. The id token is being refreshed correctly and thus have a new id token. However the "aud" seems to be overwritten with the client id. This happens whether the token has expired or not.
{
"iss": "https://accounts.google.com",
"at_h ash": "xxxxxxxxxxxxxxxxxxxxxx",
"aud": "xxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxx7dde.apps.googleusercontent.com"",
"sub": "xxxxxxxxxxxxxxxxxxxxxx",
"email_verified": true,
"azp": "xxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxx7dde.apps.googleusercontent.com",
"email": "2222MyNewEmailIsHere#gmail.com",
"iat": 1475747692,
"exp": 1475751292
}
As you can see, the "aud" and the "azp" is the same in the second response. When I then go to make a request to the server it's complaining that the token can't be verified.
I am wondering if anyone else has experienced this? It seems like an issue with GIDSignIn maybe.

Not getting all profile informations when verifying a google token authenticity

I'm using omniauth on client-side to connect with a google account. Everything is working well, I'm able to get the id_token and some more informations such as the email, name, family_name, given_name etc...
Here is how I configured the provider in app/config/initializer/omniauth.rb :
provider :google_oauth2, ENV['GOOGLE_ID'], ENV['GOOGLE_SECRET'], scope: "profile,email"
Then, as a test, to verify the authenticity of the id_token, using Postman I send a POST request such as:
https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=x
replacing x by the id_token I got on my client
I get a valid answer such as :
{
"iss": "accounts.google.com",
"at_hash": "xxx-xxx",
"aud": "xxx-xxx.apps.googleusercontent.com",
"sub": "xxx",
"email_verified": "true",
"azp": "xxx-xxx.apps.googleusercontent.com",
"email": "xxx#gmail.com",
"iat": "xxx",
"exp": "xxx",
"alg": "xxx",
"kid": "xxx"
}
When I connected with my client, I allowed the application to access my profile informations and my email, and I've been following this tuto:
https://developers.google.com/identity/sign-in/web/backend-auth
who says :
// These seven fields are only included when the user has granted the "profile" and
// "email" OAuth scopes to the application.
"email": "testuser#gmail.com",
"email_verified": "true",
"name" : "Test User",
"picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg",
"given_name": "Test",
"family_name": "User",
"locale": "en"
I can't figure out why I'm unable to get the 5 last fields
I'm working on an API and I'd like my API to be able to fill a User model by itself, only by getting the id_token.
I'm able to get those informations on the client-side but I think this is not the client job to send this extra informations to my API right?
Token calls don't include profile info... for that you muse use:
https://www.googleapis.com/plus/v1/people/me/openIdConnect?access_token=YOUR_ACCESS_TOKEN
Since you are doing this with ruby there are 2 things i can suggest trying
Try adding your scopes as an array ["profile", "email"]
Add an extra parameter fetch_basic_profile from here

What all these fields mean?

When doing cross platform authentication, you can get an ID token from your Android app using the GoogleApiClient, which you can give to your backend server. The server will then first verify the token using the following url:
https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=XYZ123
If the token is properly signed and the iss and exp claims have the expected values, you will get a HTTP 200 response, where the body contains the JSON-formatted ID token claims. Here's an example response:
{
"iss": "https://accounts.google.com",
"sub": "110169484474386276334",
"azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"email": "billd1600#gmail.com",
"at_hash": "X_B3Z3Fi4udZ2mf75RWo3w",
"email_verified": "true",
"aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"iat": "1433978353",
"exp": "1433981953"
}
What does all these fields mean aside from email?
Claims contains a set of name/value pairs
iss: The issuer of the token
sub: The subject of the token.An identifier for the user, unique among all Google accounts and never reused.
azp: The client_id of the authorized presenter.
at_hash: Access token hash. Provides validation that the access token is tied to the identity token.
email_verified: True if the user's e-mail address has been verified; otherwise false.
aud: Identifies the audience that this ID token is intended for. It must be one of the OAuth 2.0 client IDs of your application.
iat: The time the ID token was issued, represented in Unix time (integer seconds).
exp: The time the ID token expires, represented in Unix time (integer seconds).
See: https://developers.google.com/identity/protocols/OpenIDConnect
for more details.

Resources