how can I test the Keycloak native services
The documentation presents several services such as: users management, customers, groups and sessions, I have tried in many ways to test these services and without success. Perhaps due to the incorrect configuration
I saw an example on Stackoverflow that showed the correct path for services
Eg.
http://{address-and-port}/auth/admin/realms/{Realm}/users
And some settings on how to test on the postman, but I did not succeed in invoking
does anyone have an example or can help me how to activate / consume these services.
Thanks!
Services to consume: (Keycloak Admin REST API)
https://www.keycloak.org/docs-api/8.0/rest-api/index.html]
I exported you a Postman Collection: https://pastebin.com/Aaf3BUah you can import it into postman.
But I want to point out, how to use the API:
My example uses a running keycloak instance (8.0.2) on
http://localhost:80
with the user admin and the password Pa55w0rd
In consists of 2 requests:
Login:
Login with my admin user and fetch a access-token used in Request 2.
POST http://localhost:80/auth/realms/master/protocol/openid-connect/token
Content-Type:x-www-form-urlencoded
with the following parameters (change username/password)
username:admin
password:Pa55w0rd
grant_type:password
client_id:admin-cli
As a result i will get some data, but important is the access_Token-Bearer:
{
"access_token": "eyJhbGc...JDjfg", //i reduced the string
...
}
Keep in mind, this token is necessary to execute Request2. But it is only valid for 60 seconds, so be fast while testing :-)
Get all Users:
GET http://localhost:80/auth/admin/realms/master/users
Header Authorization: Bearer eyJhbGc...JDjfg
Response:
[
{
"id": "9fec4b6c-3648-425b-a90f-f6dd78f421ab",
"createdTimestamp": 1581017581626,
"username": "admin",
"enabled": true,
"totp": false,
"emailVerified": false,
"disableableCredentialTypes": [],
"requiredActions": [],
"notBefore": 0,
"access": {
"manageGroupMembership": true,
"view": true,
"mapRoles": true,
"impersonate": true,
"manage": true
}
}
]
With this example, you should be able to access different REST API endpoints. But make sure you include a valid access_token in every request you send - otherwise you will just get Not Authorized response
Here is the full Postman Administration Rest API of keycloak
https://documenter.getpostman.com/view/7294517/SzmfZHnd
It is for keycloak 10 (but work for 11 too - tested)
Open it in postman, adjust environment variables with your keycloak host and params.
You will get a full functionnal keycloak admin rest api.
Related
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.
This is related to keycloak clients. My frontend is connected to public client and backend is connected to confidential client.
I am able to login, get the code, as I am using response_type=code by turning on "Standard Flow Enabled".
This code redirects and returns me Idtoken, refreshtoken and token.
Now I need to communicate with backend which is confidential, I would like to authenticate user using some of the values which I have received from the frontend client.
How can I do that?
Here is my frontend and backend conf
FRONTEND
{
"realm": "xyz",
"auth-server-url": "http://localhost:8333/auth/",
"ssl-required": "external",
"resource": "frontend-app",
"public-client": true,
"confidential-port": 0,
"enable-cors": true
}
BACKEND
keycloak.auth-server-url=http://localhost:8333/auth
keycloak.realm=xyz
keycloak.resource=backend-app
keycloak.principal-attribute=preferred_username
keycloak.bearer-only=true
keycloak.credentials.secret=xxx-xxx-xxx
this is from realm setting
This might help somebody.
My backend service which is springboot project with spring security keycloakAuthenticationProvider does authenticate the token received from the frontend public client.
Call from frontend
axios({
method: 'GET',
url: '/api/authenticate',
headers:{'Authorization': 'Bearer '+keycloak.token+''}
}).then((r) => {
console.log("response",r)
})
Call to backend
#GetMapping("/api/authenticate")
public ResponseEntity<SecureUserDto> authenticate() {
String username = SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString();
User user = userRepository.findWithPrivilegesByUsername(username);
return ResponseEntity.ok();
}
But i still was not able to get it right on postman at ../token end point provided by keycloak server.
Anyways my work is done.
keycloak js version -> ^10.0.2
angular -> ^7.2.16
keycloak.json
{
"realm": "REALM",
"auth-server-url": "<auth-url>/auth/",
"ssl-required": "external",
"resource": "CLIENT_ID",
"verify-token-audience": true,
"credentials": {
"secret": "CLIENT_SECRET_KEY"
},
"use-resource-role-mappings": true,
"confidential-port": 0,
"policy-enforcer": {}
}
using in init like this
const keycloakAuth = Keycloak('keycloak.json');
keycloakAuth.init({ onLoad: 'login-required', checkLoginIframe: false })
when keycloak made this call <auth-url>/auth/realms/guavus/protocol/openid-connect/token than giving this error.
{"error":"unauthorized_client","error_description":"Client secret not provided in request"}
as per documentation removed credential support from javascript adapter
than what is the alternative of this and how to fix this error?
If this is an Angular Single Page Application (SPA), you should be using a public client (which will not use a client secret) per the Keycloak docs:
"One important thing to note about using client-side applications is that the client has to be a public client as there is no secure way to store client credentials in a client-side application."
https://www.keycloak.org/docs/latest/securing_apps/#_javascript_adapter
Yes, I got to know that they removed credential support from javascript adapter
https://www.keycloak.org/docs/latest/release_notes/#credentials-support-removed-from-the-javascript-adapter
https://github.com/keycloak/keycloak/commit/913056b2b2d39707347a39dddb7bdad69fe47cc3
and for javascript adapter they mentioned in document
To use the JavaScript adapter you must first create a client for your application in the Keycloak Administration Console. Make sure public is selected for Access Type.
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!
In order to have repeatable deployments of keycloak I'm trying to use the import feature to create clients in keycloak. I have noticed that when I import a client, as opposed to the realm, the 'Authorization Enabled' flag is not set to true even if I have set it to true in the JSON that I'm importing. If I try to set it to true after importing I get an error unless I first turn off 'Service Accounts Enabled' and then attempt to enable 'Authorization Enabled'.
The JSON that I'm sending is provided below:
{
"clientId" : "hello-world-authz-service",
"secret" : "secret",
"authorizationServicesEnabled" : True,
"enabled" : True,
"redirectUris" : [ "http://localhost:8080/hello-world-authz-service/*" ],
"baseUrl": "http://localhost:8080/hello-world-authz-service",
"adminUrl": "http://localhost:8080/hello-world-authz-service",
"directAccessGrantsEnabled" : True
}
The JSON above is actually based upon one of the examples that was provided in the keycloak source code and it works when I import everything as a realm, but not when I use just the client portion.
Can anyone provide guidance in regards to how I can import JSON into Keycloak in order to setup a specific client?
I'm using Keycloak 2.5.0.Final Community.
It looks like this issue might have been resolved by this pull request:
https://github.com/keycloak/keycloak/commit/0b5b27ea3a9d68a26e9cd592a1b087ea7478a07c
I can see in the pull request that the code references the authorizationServicesEnabled field.