How to remove attributes from the Keycloak JWT access token? - oauth-2.0

By default Keycloak generates the token with following payloads:
{
"jti": "71ac4939-03cb-4ce2-b072-08fa7e1b7f37",
"exp": 1560239903,
"nbf": 0,
"iat": 1560239843,
"iss": "http://localhost:8080/auth/realms/master",
"sub": "d3ea1306-f0f9-4b25-b7c5-e64dfbdf949e",
"typ": "Bearer",
"azp": "admin-cli",
"auth_time": 0,
"session_state": "0162e8c3-25b3-4fd9-8416-e28bd27b61bd",
"acr": "1",
"scope": "email profile",
"email_verified": false,
"preferred_username": "admin"
}
We can use protocol mapper to add custom fields, but is it possible to remove unnecessary fields? For example I do not want acr, email_verified, azp, and etc…

Configure mappers and client scopes properly. Each scope has its own set of configured protocol mappers, which may add additional claim. E.g. email scope by default:
Keep in the mind: scopes can be also default, so they will be executed implicitly, without explicit definition in the auth request:

Related

Azure AD OAuth Token Claim - Populate DisplayName attribute for Application Users

When I request an OAuth token from Azure AD for an application user (using a client_id and client_secret) targeting the correct resource audience (target application), I don't know how to get Azure AD to populate a claim for the client's DisplayName attribute (primarily for an application client, but also users should work too) in Azure AD.
POST /<tenant_id>/oauth2/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_id=<client_id>&resource=<target_aud_app_uri>&client_secret=<client_secret>
{
"typ": "JWT",
"alg": "RS256",
"x5t": "xxx",
"kid": "xxx"
}.{
"aud": "<target_aud_app_uri>",
"iss": "https://sts.windows.net/<tenant_id>/",
"iat": 1619676176,
"nbf": 1619676176,
"exp": 1619680076,
"aio": "xxx",
"appid": "<client_id>",
"appidacr": "1",
"idp": "https://sts.windows.net/<tenant_id>/",
"idtyp": "app",
"oid": "xxx",
"rh": "xxx",
"roles": [
"XXX"
],
"sid": "xxx",
"sub": "xxx",
"tenant_ctry": "AU",
"tenant_region_scope": "OC",
"tid": "xxx",
"uti": "xxx",
"ver": "1.0"
}.[Signature]
In the target application configuration in Azure AD, I've added all the optional claims it allows in the UI, and even tried adding 'display_name' via the manifest but it doesn't know how to pick it up. Is there a way to do this?
This question has been asked before.
This is possible under the Microosft.graph namespace only cannot be used for any custom app. In other words, only the ms graph api token has app_displayname claim. For the token of the application custom api, it is currently not possible to add the app_displayname claim, at least for now this is impossible.
I suggest you submit user voice, and I will vote for it.

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!

Ignore invalid scopes while generating token

We are in the process of upgrading our keycloak setup from 6.0.1 to 11.0.0 and it seems like from Keycloak 10 onward the token generation complains with error "invalid scope" if the scope parameter is invalid.
Intially we were using Keycloak 3 with RBAC (user and roles assigned to them) and full scoped clients (only Direct Access Grants Enabled = true) this used to worked fine where we were passing required roles in scope and used to get access token for request roles (in scope) and later we updated it to Keycloak 6 which used to work fine with this setup as well, however updating it to Keycloak 11 breaks it since we do not use fine grained scopes so passing existing roles to scope sort of broke it, however if I do not provide any scope then it works fine.
My setup looks like below
Roles:
Role1
Role2
Role3
Users:
User1
User2
User-Role Mapping
Role1, Role2 --> User1
ROle3 --> User2
Clients
Client1
AccessType: Cofidential
Direct Access Grants: Enabled
Scoped: Full Scoped
Generated token
{
"exp": 1598869296,
"iat": 1598867496,
"jti": "b5cd4395-1ba2-471b-9e3f-86fa7c699d72",
"iss": "http://localhost:8480/auth/realms/EDP",
"aud": "account",
"sub": "2efa51cd-1afb-4f18-83c4-12e4017739b5",
"typ": "Bearer",
"azp": "service",
"session_state": "a4925385-b787-4ae7-a076-a4b92b5df87c",
"acr": "1",
"realm_access": {
"roles": [
"Rol1",
"offline_access",
"uma_authorization",
"Rol2"
]
},
"resource_access": {
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
},
"scope": "default roles",
"unique_name": "User1",
"preferred_username": "User1",
"tid": "Foo"
}

How to differentiate JWT access token from refresh token used as Authorization header

How can you determine if the JWT token used in Authorization: Bearer ... is an access token or a refresh token. In other words what prevents the user from using his JWT refresh token in the Authorization header instead of the acces token.
When I look at the payload of both the access token and the refresh token in this guide section https://github.com/starkandwayne/ultimate-guide-to-uaa/blob/master/docs/refresh-tokens.md#jwt-refresh-tokens I don't see any real way to identify which one is which.
Refresh token:
{
"jti": "3e53955fcff6429a8a187c4c37f1b592-r",
"sub": "48a8d464-12dd-4b14-b7a0-96af58379ffb",
"scope": [
"openid",
"airports.all"
],
"client_id": "airports",
"cid": "airports",
"user_id": "48a8d464-12dd-4b14-b7a0-96af58379ffb",
"origin": "uaa",
"grant_type": "password",
"user_name": "airports-all",
"rev_sig": "4c3b3810",
"iat": 1530739971,
"exp": 1533331970,
"iss": "https://192.168.50.6:8443/oauth/token",
"zid": "uaa",
"aud": [
"openid",
"airports"
]
}
Access token:
{
"jti": "fe39323464d74fb5a6fcb71d89f722c4",
"sub": "48a8d464-12dd-4b14-b7a0-96af58379ffb",
"scope": [
"openid",
"airports.all"
],
"client_id": "airports",
"cid": "airports",
"azp": "airports",
"user_id": "48a8d464-12dd-4b14-b7a0-96af58379ffb",
"origin": "uaa",
"grant_type": "password",
"user_name": "airports-all",
"email": "airports-all#example.com",
"auth_time": 1530739970,
"rev_sig": "4c3b3810",
"iat": 1530739971,
"exp": 1530783171,
"iss": "https://192.168.50.6:8443/oauth/token",
"zid": "uaa",
"aud": [
"openid",
"airports"
]
}
What is the standard? Put a different scope?
As in the link you've posted, the recommendation is to use opaque refresh tokens that are not JWTs, and you should use that configuration.
The client (usually a UI) should only ever send access tokens to the back end and any other type of token should be rejected. The correct configuration enforces this.
The back end's job is to validate the received JWT. A non standard setup as above could mean that this will work with a refresh token, but this is bad in 2 ways:
The API message credential has a very long lifetime and security risks are greater if a token is intercepted somehow
The solution is not portable and is likely to break for the client in future, or if you ever change providers

Adal.js returns a token with invalid permission with a powerbi resource

I'm having issue authenticating with Azure Active Directory which is linked to a power BI service. I'm trying to get an access token so that I can access the power bi rest API.
If i use postman, I'm able to successfully use their OAuth2 login to retrieve a token that has the correct credentials to communicate with the power bi rest API.
However, when I try to do this with the adal.js the token is invalid. To simplify this to be able to reproduced, I based my project off
https://github.com/Azure-Samples/active-directory-angularjs-singlepageapp-dotnet-webapi
You need to update window config in : \active-directory-javascript-singlepageapp-dotnet-webapi\TodoSPA\App\Scripts\app.js
window.config = {
instance: 'https://login.microsoftonline.com/',
tenant: <insert tenant>,
clientId: <insert clientid>,
postLogoutRedirectUri: window.location.origin,
cacheLocation: 'localStorage', // enable this for IE, as sessionStorage does not work for localhost.
endpoints: {
"https://api.powerbi.com": "https://analysis.windows.net/powerbi/api",
}
};
Workaround
I'm able to get the token via silent authentication where you have to hard code the username and password.
I followed this http://community.powerbi.com/t5/Developer/How-to-use-Power-BI-Rest-API-without-GUI-authentication-redirect/m-p/14218#M119 to create the request for silent authentication:
Post Url: https://login.windows.net/<tenant>/oauth2/token
Body:
password: <password>
username: <username>
client_id: <clientid>
client_secret: <secret>
grant_type: password
scope: openId
resource: https://analysis.windows.net/powerbi/api
I also validated that the account I used had the correct permission by using postman and authorization with OAuth2. The token I received had the correct permission for PowerBI.
Post Man Configuration
On postman, click on Authorization Tab -> Set Type to OAuth2.0 -> Get New Access Token:
The configuration you would use:
AuthUrl: https://login.microsoftonline.com//oauth2/authorize?resource=https://analysis.windows.net/powerbi/api
Access Token URL: https://login.microsoftonline.com//oauth2/token
Grant Type: Authorization Code:
Client ID:
Client Secret:
Go to https://dev.powerbi.com/apps to generate the clientID/ClientSecret and set the Redirect URL: https://www.getpostman.com/oauth2/callback
postman generated token:
{
"aud": "https://analysis.windows.net/powerbi/api",
"iss": "https://sts.windows.net/<id>/",
"iat": 1500464096,
"nbf": 1500464096,
"exp": 1500467996,
"acr": "1",
"aio": <value>,
"amr": [
"pwd"
],
"appid": <app_id>,
"appidacr": "1",
"family_name": "Sunderam",
"given_name": <userName>,
"ipaddr": "23.252.49.99",
"name": <name>,
"oid": <oid_id>,
"platf": "3",
"puid": <puid_id>,
"scp": "Content.Create Dashboard.Read.All Data.Alter_Any Dataset.Read.All Dataset.ReadWrite.All Group.Read Group.Read.All Metadata.View_Any Report.Read.All Report.ReadWrite.All",
"sub": <sub_id>,
"tid": <tid_id>,
"unique_name": <user_email>,
"upn": <user_email>,
"ver": "1.0",
"wids": [
<wid_id>
]
}
adal.js token
{
"aud": <aud_id>,
"iss": "https://sts.windows.net/<id>/",
"iat": 1501037728,
"nbf": 1501037728,
"exp": 1501041628,
"aio": <aio_id>",
"amr": [
"pwd"
],
"family_name": <name>,
"given_name": <name>,
"ipaddr": "23.252.49.99",
"name": ,"name"
"nonce": "b21969c3-ae73-4928-bcd0-e9c501f791e4",
"oid": <oid_id>,
"platf": "5",
"sub": <sub_id>,
"tid": <tid_id>,
"unique_name": <user_email>,
"upn": <user_email>,
"ver": "1.0"
}
Notice that the postman token has the scp, appid, and wids.
Any Advice appreciated,
Thanks,
Derek
You need to check the token via the request. For example, you can check it via the developer tools-Network tab(Chrome, F12).
And based on the token and code, the config seems incorrect. For the endpoints is the collection of {Endpoint-ResourceId} used for automatically attaching tokens in webApi calls.
You can use the config like below:
window.config = {
instance: 'https://login.microsoftonline.com/',
tenant: <insert tenant>,
clientId: <insert clientid>,
postLogoutRedirectUri: window.location.origin,
cacheLocation: 'localStorage', // enable this for IE, as sessionStorage does not work for localhost.
endpoints: {
"https://analysis.windows.net/powerbi/api": "https://api.powerbi.com",
}
};
More detail about this library, you can refer this link.

Resources