Keycloak: I can't add custom user attribute into the token? - keycloak

My users has a birthDate attribute:
I created a mapper in client:
Yet it can't be seen in access token:
{
"exp": 1646589516,
"iat": 1646589216,
"jti": "7cee1468-8d80-4f14-a118-b07477c1e1e7",
"iss": "http://localhost:8080/realms/...",
"aud": "account",
"sub": "f:fd2a5a5a-c7a0-4e74-81a8-916a85885f98:...",
"typ": "Bearer",
"azp": "...",
"session_state": "efce7a63-2a8f-438d-b4a1-f5d979a00c81",
"acr": "1",
"realm_access": {
"roles": [
"offline_access",
"uma_authorization"
]
},
"resource_access": {
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
},
"scope": "openid profile email",
"sid": "efce7a63-2a8f-438d-b4a1-f5d979a00c81",
"email_verified": false,
"preferred_username": "..."
}
Can it happen that the keycloak caching somewhere? (I cleared the caches at Realm --> Caches)
I am desperate... Every tutorial does this and it is not working for me.
Update: I could test it on a server that is remote and it is working. Where the hell the keycloak is caching and screwing me?
---------------------------------------------------------------------------
Update2: deleted the keycloak & reinstalled so start from 0:
created realm: ep
created client: ep
Here we can see the user has an attribute birthDate with value my-custom-birth-date:
I go Clients --> ep client --> Mappers and create a mapper like this:
Clients --> ep --> Client Scopes --> Evaluate --> Evaluate button we can see that the birthDate can be found there (last row, also the default birthdate can be seen):
If I evaluate on the user P...o then you can see the access token does not contains the birthDate attribute:
If I use postman to request a token for this user, the access_token looks like this:
Still missing the attribute birthDate.
I repeated every action I did above and in the remote keycloak the attribute can be seen (the last one on the image):
---------------------------------------------------------------------------
So I found the problem:
Here is my keycloak folder and the path to it:
I copied the data folder to here thinking I won't need to recreate the realm/client/etc:
Whenever I reinstalled the keycloak, I deleted the keycloak-17.0.0 folder and reinstalled to the same place:
After I deleted both data and keycloak-17.0.0 and recreate the realm/client/mappers/etc, it is working perfectly...
No idea why did the keycloak checked for configurations/settings/caches a folder above in the tree...

Related

Keycloak: Access Denied when adding claims (permission.addClaim) to RPT token

My Spring Boot Application with policy enforcer works fine. But when I add via my SPI some custom claims to the authorization->permission part of the RPT token then I am always getting: Policy enforcement result for path [http://localhost:8989/customers/1] is : DENIED
I have these lines in application.properties :
keycloak.securityConstraints[0].authRoles[0]=*
keycloak.securityConstraints[0].securityCollections[0].patterns[0]=/*
keycloak.policy-enforcer-config.enforcement-mode=enforcing
keycloak.policy-enforcer-config.paths[0].path=/customers/*
keycloak.policy-enforcer-config.paths[0].methods[0].method=GET
keycloak.policy-enforcer-config.paths[0].methods[0].scopes[0]=view
My RPT token looks like:
"authorization": {
"permissions": [
{
"scopes": [
"view"
],
"claims": {
"customers:view:country": [
"[Belgium]"
]
},
"rsid": "fe8b4cd1-601b-46cf-9f2b-1534ade8cab2",
"rsname": "customers"
}
]
},
When the "claims" part is added access is denied.
Any idea why it is always denied?
The policy enforcer should actually ignore those additions, right?
It should evaluate access based on resource and scope in the RPT token.
Is there a way to disable this additional claims check?

Which roles enable a user in a Keycloak Realm to use the Admin-REST-API?

Which roles / configuration are needed for a user that is not in the master realm to effectively use the Keycloak 15 Admin REST API?
We are successfully using an account that is assigned the realm-admin role in the realm-management client to get a token for the admin-cli client.
This still works.
I can not recall for how long, but after the migration from KC 14 to KC 15 we now experience 403 Errors when trying to call admin cli endpoints like:
/auth/admin/realms/${realm}/users/${userID}/role-mappings/clients/${appClientUUID}
/auth/admin/realms/${realm}/users/${userid}
etc.
If it would throw 401s I would know that it is at least a credential problem, but the token endpoint does push out an access token:
{
"alg": "RS256",
"typ": "JWT",
"kid": "{kid}"
}.{
"exp": 1635328475,
"iat": 1635328175,
"jti": "b621421d-ad69-4ddf-bedb-2c0d5da360cd",
"iss": "{keycloak URL}",
"sub": "{subvalue}",
"typ": "Bearer",
"azp": "admin-cli",
"session_state": "{uuid}",
"acr": "1",
"scope": "openid email profile",
"sid": "986dce48-2ef2-49e5-9152-4e54396ff2a4",
"email_verified": true,
"name": "-",
"preferred_username": "-",
"given_name": "-",
"family_name": "-",
"email": "-"
}.[Signature]
What surprises me is the case that there seem to be no roles contained in the token.
Does anyone have a clue what might have gone wrong / has been misconfigured for KC 15 regarding the Admin Rest API?
Turns out the only problem here was the protocol I specified when making the request. Sometimes schoolboy errors happen.
For those who turn up here googling the same thing: Check if your user has the role of realm-admin in the client realm-management assigned. Everything else is handled internally by Keycloak.

Using OAuth 2 to authenticate to Azure DevOps REST APIs fails with TF400813 (user not authorized)

I am following the documentation posted here (https://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/oauth?view=azure-devops).
I have a react-based webapp and a powershell-based function app, both in Azure. My function app is presently using a personal access token created with my work account (AAD) credentials, which is not desirable. My goal is to use OAuth2 to authorize my function app to make code changes to a GIT repository on behalf of a webapp user. When I follow the instructions above, I am able to acquire what appears to be a valid authorization code, access token, and refresh token, I receive the following error message from Azure DevOps:
TF400813: The user 'ffffffff-ffff-ffff-ffff-ffffffffffff' is not authorized to access this resource.
…
401 - Uh-oh, you do not have access.
The request requires authentication.
4/21/2021 12:04:16 AM (UTC)
ffffffff-ffff-ffff-ffff-ffffffffffff
Sign out and login with different account
I have obscured the guids in the example above, but the user GUID appears to match the GUID I find for my work account when I call the legacy identity APIs (https://learn.microsoft.com/en-us/rest/api/azure/devops/ims/identities/read%20identities?view=azure-devops-rest-6.0).
I created my application (https://app.vsaex.visualstudio.com/app/register) with the same scopes that I used to create my personal access token. I verified in my dev.azure.com profile that my application is listed as an authorized OAuth app, as expected after creating the authorization request and receiving the authorization code.
The error message above is confusing to me. It says that the user (me) is not authorized to access the resource but also says that the authentication failed. Which is it?
Is this a problem with how I am acquiring my authorization/access tokens? Am I somehow using the wrong account? Are my scopes wrong?
Reproduction of Problem
Here is the state from my registered application:
My application state:
{
"scopes": "vso.code_full vso.code_status vso.graph_manage vso.identity_manage vso.threads_full vso.tokens",
"tokenUrl": "https://app.vssps.visualstudio.com/oauth2/token",
"state": "foo",
"authCallback": "https://myapp.azurewebsites.net/oauth-callback",
"clientSecret": "S.S.S-S-S",
"authUrl": "https://app.vssps.visualstudio.com/oauth2/authorize",
"appWebsite": "https://myapp.azurewebsites.net/",
"appSecret": "S",
"appId": "FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF"
}
Step 1. Authorize the application.
I invoke the following auth URI from an in-private browser.
I authenticate my work account, and authorize the application for the requested scopes.
I can verify the app is an authorized oauth app in my dev.azure.com profile.
https://app.vssps.visualstudio.com/oauth2/authorize?client_id=FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF&response_type=Assertion&state=foo&scope=vso.code_full%20vso.code_status%20vso.graph_manage%20vso.identity_manage%20vso.threads_full%20vso.tokens&redirect_uri=https://myapp.azurewebsites.net/oauth-callback
I receive an authcode, "A.A.A-A-A-A" (shown decoded/obfuscated below):
{
"typ": "JWT",
"alg": "RS256",
"x5t": "....."
}
{
"cid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
"csi": "ffffffff-ffff-ffff-ffff-ffffffffffff",
"nameid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
"iss": "app.vstoken.visualstudio.com",
"aud": "app.vstoken.visualstudio.com",
"nbf": 1618438026,
"exp": 1776204426
}
Step 2. Request the access token and refresh token from my powershell function app:
I make a rest api call to the token endpoint:
"Uri": "https://app.vssps.visualstudio.com/oauth2/token"
"Method": "POST"
"ContentType": "application/x-www-form-urlencoded"
"Body": "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion=S.S.S-S-S&grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=A.A.A-A-A-A&redirect_uri=https://myapp.azurewebsites.net/oauth-callback"
…and I get the following JSON response:
Token Response:
{
"access_token": "X.X.X-X-X-X-X-X-X",
"token_type": "jwt-bearer"
"expires_in": 3599,
"refresh_token": "R.R.R-R-R-R",
"scope": "vso.code_full vso.code_status vso.graph_manage vso.identity_manage vso.threads_full vso.tokens vso.authorization_grant"
}
Yielding the following JWT for the access token:
{
"typ": "JWT",
"alg": "RS256",
"x5t": "....."
}
{
"nameid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
"scp": "vso.code_full vso.code_status vso.graph_manage vso.identity_manage vso.threads_full vso.tokens",
"aui": "ffffffff-ffff-ffff-ffff-ffffffffffff",
"appid": "ffffffff-ffff-ffff-ffff-ffffffffffff",
"iss": "app.vstoken.visualstudio.com",
"aud": "app.vstoken.visualstudio.com",
"nbf": 1618963456,
"exp": 1618967056
}
Step 3. Make a DevOps REST API call.
In this case, I am requesting a list of respositories in my org/project:
"Uri": "https://dev.azure.com/myorg/myproj/_apis/git/repositories?api-version=6.0"
"Method": "GET"
"Headers": {"Authorization": "Bearer X.X.X-X-X-X-X-X-X"}
This is where things go wrong. DevOps returns a 401 error indicating that my account is not authorized.
TF400813: The user 'ffffffff-ffff-ffff-ffff-ffffffffffff' is not authorized to access this resource.
If I make the exact same http GET from Step 3, but I substitute my PAT with identical scopes as the registered application, the call succeeds. The PAT seems to be created with the exact same profile/account that is authorized in Step 1.
This behavior can be observed when the organization admins have disabled OAuth in the settings. The relevant option can be viewed by any member of the org at e.g. https://dev.azure.com/contoso/_settings/organizationPolicy
Sadly there is no better indication of this for the app or the user, as far as I can see.
Your app can still ask the user for authorization, all OAuth operations succeed, a seemingly valid access token gets returned, but then it simply does not work and returns 401 from all APIs, even if a PAT with the same scope(s) works fine.

Obtain action token (reset password) with keycloak admin api

I'm trying to implement the forgot password flow with key-cloak and was able to do it with key-cloak admin UI. But now I want to do this reset flow completely inside the web application without forwarding the user to key-cloak. By observing the reset token (action token) sent to the email it shows it has attributes such as type and expiry.
{
"jti": "xx",
"exp": 1553850003,
"nbf": 0,
"iat": 1553846403,
"iss": "xxx",
"aud": "xxx",
"sub": "6eabb442-d40d-4857-8b8f-xxx",
"typ": "reset-credentials",
"nonce": "xxx",
"asid": "xxxx"
}
The admin Api provides an api to reset password but I cannot find an api to obtain an action token/forgot password api. Would be much obliged if I could know how to approach this workflow with key-cloak admin.

How to impersonate the user in Jira add-on to use Jira REST API on behalf of user

I'm looking for help of somebody who knows something about Jira add-ons.
I'm trying to implement Jira add-on with an ability to create issues on behalf of a user.
So, I completed all steps (as I think) leading me to my goal, but I faced a problem with impersonating. When I try to create an issue using Jira REST API, I receive the following error:
{
"error": "Add-on 'com.example.myapp' disallowed to impersonate the user because 'no valid active user exists'"
}
What was done:
Folowing the getting started tutorial I created the add-on descriptor:
{
"name": "Hello World",
"description": "Atlassian Connect app",
"key": "com.example.myapp",
"baseUrl": "https://url.ngrok.io",
"vendor": {
"name": "Example, Inc.",
"url": "http://example.com"
},
"authentication": {
"type": "jwt"
},
"scopes": [
"act_as_user",
"read",
"write",
],
"lifecycle": {
"installed": "/api/created",
},
"apiVersion": 1
}
I also implemented webhook to handle 'installed' callback from add-on like described here. So, when a user installs the add-on the webhook will receive the following object:
{
'key': 'com.example.myapp',
'clientKey': '<client key>',
'oauthClientId': '<OAuth client ID>',
'publicKey': '<public key>',
'sharedSecret': '<shared secret>',
'serverVersion': '100095',
'pluginsVersion': '1.250.0',
'baseUrl': 'https://<user's domain>.atlassian.net',
'productType': 'jira',
'description': 'Description',
'eventType': 'installed'
}
Using this data I generated JWT signed with the shared secret like described in the tutorial. So, my JWT payload includes the following claims:
{
'iss': 'urn:atlassian:connect:clientid:<OAuth client ID>',
'sub': 'urn:atlassian:connect:useraccountid:<client key>',
'tnt': 'https://<user's domain>.atlassian.net',
'iss': '<created at>',
'exp': '<created at + 1 minute>'
}
The next step I performed is access token generation using auth.atlassian.io/oauth2/token endpoint and the following parameters:
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=<my JWT>&scope=ACT_AS_USER READ WRITE
The result of all these actions is an access token witch I can use to perform REST API requests. But the error described above returned every time I try to create Jira issue performing POST [user's domain].atlassian.net/rest/api/2/issue/ with Authorization: Bearer [access_token] header.
What I've noticed is that account ID in installed callback object (clientKey) has 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' (uuid) format. But when I open my account in Jira (account in witch the add-on is installed) I see that the account ID in URL has 'YYYYYY:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' format. I prepended the subject in my JWT payload with YYYYYY part:
'sub': 'urn:atlassian:connect:useraccountid:'YYYYYY:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
and generated a new access token using this JWT. I've used new access token to create an issue and it was successfully created, the reporter of the issue is a user installed my add-on, just like I wished.
Finally, the question is: where can I find that YYYYYY part for my add-on? How to get it automatically? What I've missed following the tutorials? Any help will be appreciated.
Thank you!