Keycloak Bear-Only Client with and without Authorization Client Secret - keycloak

In keycloak when I set up a Client as a bearer-only Access Type and without Authorization I get the following config for installation on my server
{
"realm": "API",
"bearer-only": true,
"auth-server-url": "https://example.com.au/auth/1.0",
"ssl-required": "none",
"resource": "edge-server"
}
Then when I enable Authorization for that client it now includes the client secret:
{
"realm": "API",
"bearer-only": true,
"auth-server-url": "https://example.com.au/auth/1.0",
"ssl-required": "none",
"resource": "edge-server",
"credentials": {
"secret": "33333333-4444-5555-6666-777777777777"
},
"policy-enforcer": {}
}
So my question is why would my server need the secret when Authorizations are enabled?

Keycloak Authorization policies can only be applied to confidential clients such as your backend REST API.

Related

Open Liberty Microprofile-JWT always returns 401

I'm currently working on implementing JWT authentication on our backend via microprofile jwt (v1.2) on an Open Liberty server (v22.0.7.). The JWT is issued by a keycloak server.
It seems, I am somewhere mistaken though, because all my API calls return '401 Unauthorized' as soon as I add the RolesAllowed Annotation. And according to traces the principal is null.
My Microprofile properties (sensitive information in [ ]):
mp.jwt.verify.publickey.location=[host]/realms/[realm]/protocol/openid-connect/certs
mp.jwt.verify.issuer=[host]/realms/[realm]
mp.jwt.verify.id=myJWT
mp.jwt.verify.userNameAttribute=upn
mp.jwt.verify.audiences=backend
I also tried:
META-INF/micro-profile.properties:
mp.jwt.verify.publickey.location=[host]/realms/[realm]/protocol/openid-connect/certs
mp.jwt.verify.issuer=[host]/realms/[realm]
server.xml:
<mpJwt
id="myJWT"
userNameAttribute="upn"
audiences="backend"
/>
My Resource class:
#Path("/[path]")
#RolesAllowed({ "Authenticated" })
public class MyResource implements MyApi {
[...]
}
My Application class:
#LoginConfig(authMethod = "MP-JWT")
public class MyApplication extends Application {
}
My token payload:
"exp": 1662994046,
"iat": 1662986846,
"jti": "a0a92213-ae77-43fd-b0b8-8cb2f15524b2",
"iss": "[host]/realms/[realm]",
"aud": [
"backend"
],
"sub": "6194ef8a-dbe2-46fb-aa88-64dd61b4c8bc",
"typ": "Bearer",
"azp": "frontend",
"session_state": "6c60affa-b613-49cd-8e8b-a06b16eb8e61",
"acr": "1",
"scope": "microprofile-jwt",
"sid": "6c60affa-b613-49cd-8e8b-a06b16eb8e61",
"upn": "name",
"groups": [
"Authenticated"
]
}
I also tried the suggestion in Microprofile JWT responding with 401 all the time to no avail.
My API calls are made like normal, with the added Header:
"Authorization: Bearer [token]"
Finally you can find tracing in this pastebin

Create a new user trough AWS ApiGateway secured with Cognito - how to allow access to the users before it is created?

I have an API in AWS API gateway secured with AWS-Cognito. In order to use the endpoint the user must to be recognized by Cognito that will return a token.
The question here is related to the CREATE USER process. In order to use this endpoint the user must to exist in the Cognito, then receive the token and use it to connect to the CREATE USER endpoint. But at the moment of the creation of the user in the database (api-endpoint) the user is not created in Cognito and has no permission to get access to the API.
So, how should be the best approach to this process?
You don't need to always use the TOKEN authorizer. API Gateway allows you to configure another type of authorizer: REQUEST.
In that case it's entirely up to you how you want to tell if someone is (or is not) authorized to make a call to your API endpoint.
The event will look something like this (taken from AWS documentation):
{
"type": "REQUEST",
"methodArn": "arn:aws:execute-api:us-east-1:123456789012:abcdef123/test/GET/request",
"resource": "/request",
"path": "/request",
"httpMethod": "GET",
"headers": {
"X-AMZ-Date": "20170718T062915Z",
"Accept": "*/*",
"HeaderAuth1": "headerValue1",
"CloudFront-Viewer-Country": "US",
"CloudFront-Forwarded-Proto": "https",
"CloudFront-Is-Tablet-Viewer": "false",
"CloudFront-Is-Mobile-Viewer": "false",
"User-Agent": "..."
},
"queryStringParameters": {
"QueryString1": "queryValue1"
},
"pathParameters": {},
"stageVariables": {
"StageVar1": "stageValue1"
},
"requestContext": {
"path": "/request",
"accountId": "123456789012",
"resourceId": "05c7jb",
"stage": "test",
"requestId": "...",
"identity": {
"apiKey": "...",
"sourceIp": "...",
"clientCert": {
"clientCertPem": "CERT_CONTENT",
"subjectDN": "www.example.com",
"issuerDN": "Example issuer",
"serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1",
"validity": {
"notBefore": "May 28 12:30:02 2019 GMT",
"notAfter": "Aug 5 09:36:04 2021 GMT"
}
}
},
"resourcePath": "/request",
"httpMethod": "GET",
"apiId": "abcdef123"
}
}
Then you need to tell API Gateway that it can pass this response through:
{
"principalId": "any-identifier-you-choose-like-uuid",
"policyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Allow",
"Resource": "arn:aws:execute-api:eu-west-1:111111111111:abcdef/prod/GET/myresource"
]
}
}
There is also caching policy involved, but this should be enough for you to start.

Keycloak: Access token client-1 to manage client-2 resources

I have two clients in Keycloak:
CP: Client public
CC: Client confidential with Service Accounts enabled and several resources.
Resources owners are users who created them and they manage the access too.
The User (U) who created the Resource (R) can log in to CC and use the access token for call endpoints on CP.
Now I would like U will be able to set UMA policies, but the access token is from CP, not from CC where the resources are, so Keycloak is complaining about de token.
org.keycloak.authorization.client.util.HttpResponseException: Unexpected response from server: 403 / Forbidden / Response from server: {\"error\":\"invalid_clientId\",\"error_description\":\"Client application [CP] is not registered as a resource server.\"}
fun onlyOwner(accessToken: String, id: String, resourceId: String) {
val request = UmaPermissionRepresentation()
request.name = "Only owner can view $id"
request.description = "Only owner can view this resource"
request.scopes = setOf(ResourceScope.VIEW)
request.condition = ONLY_OWNER_CONDITION
authzClient.protection(accessToken).policy(resourceId).create(request)
}
Keycloak docs mention the following:
"
The Policy API is available at:
http://${host}:${port}/auth/realms/${realm_name}/authz/protection/uma-policy/{resource_id} This API is protected by a bearer token that must represent a consent granted by the user to the resource server to manage permissions on his behalf. The bearer token can be a regular access token obtained from the token endpoint using:
Resource Owner Password Credentials Grant Type
Token Exchange, in order to exchange an access token granted to some client (public client) for a token where audience is the resource server
I exchanged the CP client to CC client:
Original token:
{
"exp": 1606687405,
"iat": 1606651407,
"auth_time": 1606651405,
"jti": "1e4075a9-ce49-4462-91f7-33b8963f56dd",
"iss": "http://localhost/auth/realms/test",
"aud": "account",
"sub": "8381b629-5f10-401c-ae90-bb37769e5f70",
"typ": "Bearer",
"azp": "CP",
"session_state": "6c2d73e7-a4bd-44da-b242-cdf26ec812bc",
"acr": "1",
"allowed-origins": [
"*"
],
"realm_access": {
"roles": [
"offline_access",
"uma_authorization"
]
},
"resource_access": {
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
},
"scope": "openid email profile",
"email_verified": true,
"name": "Test First",
"preferred_username": "test",
"given_name": "Test",
"family_name": "First",
"email": "test#invent.com"
}
Exchanged token:
{
"exp": 1606687405,
"iat": 1606652039,
"auth_time": 1606651405,
"jti": "0c84f42a-973e-4bc7-9a6d-2c4fec548512",
"iss": "http://localhost/auth/realms/test",
"aud": [
"account",
"CC"
],
"sub": "8381b629-5f10-401c-ae90-bb37769e5f70",
"typ": "Bearer",
"azp": "CP",
"session_state": "6c2d73e7-a4bd-44da-b242-cdf26ec812bc",
"acr": "1",
"allowed-origins": [
"http://localhost"
],
"realm_access": {
"roles": [
"offline_access",
"uma_authorization"
]
},
"resource_access": {
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
},
"scope": "email profile",
"email_verified": true,
"name": "Test First",
"preferred_username": "test",
"given_name": "Test",
"family_name": "First",
"email": "test#invent.com"
}
But the error persists alghout aud changed from account to [account,cc].
The solution is exchanging the token using as client_id and client_secret the target client (cc). After that, you can use the access_token returned by Keycloak as bearer token for creating the UMA_Policy.
Exchange public client token to the confidential client token
Create a policy with the new access token

Azure DevOps OAuth organization policies API

is there a way to know via API what is the organization policy for 3rd party OAuth requests?
i want to know if i should ask my user to authenticate with his credentials or generate PAT
is there a way to know via API what is the organization policy for 3rd
party OAuth requests?
You can use this api which I fetched from F12:
Get https://dev.azure.com/{YourOrgName}/_settings/organizationPolicy?__rt=fps&__ver=2
The response would contain the info about Application Connection Policies:
"ms.vss-admin-web.organization-policies-data-provider": {
"policies": {
"applicationConnection": [
{
"policy": {
"name": "Policy.DisallowOAuthAuthentication",
"value": false,
"effectiveValue": true,
"parentPolicy": {
"name": "Policy.DisallowOAuthAuthentication",
"value": false,
"effectiveValue": true,
"isValueUndefined": true
}
},
"learnMoreLink": "https://aka.ms/vstspolicyoauth",
"description": "Third-party application access via OAuth",
"applicableServiceHost": 1
},
{
"policy": {
"name": "Policy.DisallowSecureShell",
"value": false,
"effectiveValue": true,
"isValueUndefined": true,
"parentPolicy": {
"name": "Policy.DisallowSecureShell",
"value": false,
"effectiveValue": true,
"isValueUndefined": true
}
},
"learnMoreLink": "https://aka.ms/vstspolicyssh",
"description": "SSH authentication",
"applicableServiceHost": 1
}
]...
The effectiveValue(not value node) node under corresponding policy node should represent whether you enable/disable the policies above in your pic. E.g: The effectiveValue node under first policy node would be false if the Third-party application access via OAuth is disabled.

Setting up keycloak bearer-only client with https keycloak server

I have been trying to setup keycloak bearer-only client.Followed the steps mentioned in the keycloak documentation for javascript adapter. http works fine. With https, I was getting "Access Denied".
Below is the keycloak.json used in the client.
{
"realm": "MyRealm",
"auth-server-url": "https://10.65.107.118:8043/auth",
"ssl-required": "none",
"resource": "edge",
"bearer-only": true,
"public-client": true,
"use-resource-role-mappings": true,
"confidential-port": 0
}
The solution is to add "realm-public-key" in the keycloak.json.
The value of realm-public-key can be found from keycloak server. That is going to realm settings , one can find the public-key and copy-paste it in keycloak.json,to be used by client apps of this realm.
{
"realm": "MyRealm",
"auth-server-url": "https://10.65.107.118:8043/auth",
"ssl-required": "none",
"resource": "edge",
"bearer-only": true,
"public-client": true,
"use-resource-role-mappings": true,
"confidential-port": 0,
"realm-public-key": "MIIBIjANBgkqh..."
}
hope this helps somebody!