JWKS URI missing in JWT based on Keycloak Client - jwt

I have activated the JWKS_URI in my OAuth client (within Keycloak).
[]
Now, my expectation was that besides the KID an field JWKS_UIR will be part of the JWT for that client. But, I see only KID. The CERTS endpoint works and response with a JWKS Json format.
Is my understanding correct that the JWKS_URI should be in the Token? (see https://www.rfc-editor.org/rfc/rfc8414.html)

From rfc8414.html , in 3.2. Authorization Server Metadata Response section.
The JWKS_URI is in the Authorization Server Metadata Response
It is response of 3.1. Authorization Server Metadata Request
and request example is
GET /.well-known/oauth-authorization-server HTTP/1.1
Host: example.com
example response
{
"issuer":
"https://server.example.com",
"authorization_endpoint":
"https://server.example.com/authorize",
"token_endpoint":
"https://server.example.com/token",
"token_endpoint_auth_methods_supported":
["client_secret_basic", "private_key_jwt"],
"token_endpoint_auth_signing_alg_values_supported":
["RS256", "ES256"],
"userinfo_endpoint":
"https://server.example.com/userinfo",
"jwks_uri":
"https://server.example.com/jwks.json",
"registration_endpoint":
"https://server.example.com/register",
"scopes_supported":
["openid", "profile", "email", "address",
"phone", "offline_access"],
"response_types_supported":
["code", "code token"],
"service_documentation":
"http://server.example.com/service_documentation.html",
"ui_locales_supported":
["en-US", "en-GB", "en-CA", "fr-FR", "fr-CA"]
}
In the Keycloak, provide this API
http://keycloakhost:keycloakport/auth/realms/{realm}/.well-known/openid-configuration
"jwks_uri" (Certificate endpoint) is it response as following JSON.
{
"issuer": "http://localhost:8080/auth/realms/my-realm",
"authorization_endpoint": "http://localhost:8080/auth/realms/my-realm/protocol/openid-connect/auth",
"token_endpoint": "http://localhost:8080/auth/realms/my-realm/protocol/openid-connect/token",
"introspection_endpoint": "http://localhost:8080/auth/realms/my-realm/protocol/openid-connect/token/introspect",
"userinfo_endpoint": "http://localhost:8080/auth/realms/my-realm/protocol/openid-connect/userinfo",
"end_session_endpoint": "http://localhost:8080/auth/realms/my-realm/protocol/openid-connect/logout",
"frontchannel_logout_session_supported": true,
"frontchannel_logout_supported": true,
"jwks_uri": "http://localhost:8080/auth/realms/my-realm/protocol/openid-connect/certs",
"check_session_iframe": "http://localhost:8080/auth/realms/my-realm/protocol/openid-connect/login-status-iframe.html",
"grant_types_supported": [
"authorization_code",
"implicit",
"refresh_token",
"password",
"client_credentials",
"urn:ietf:params:oauth:grant-type:device_code",
"urn:openid:params:grant-type:ciba"
],
"response_types_supported": [
"code",
"none",
"id_token",
"token",
"id_token token",
"code id_token",
"code token",
"code id_token token"
],
"subject_types_supported": [
"public",
"pairwise"
],
"id_token_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512"
],
...
You shows header of JWT
In the specification JWT RFC 7519,
The example shows only "typ" and "alg" not "jwks_uri"
{"typ":"JWT",
"alg":"HS256"}

Related

Getting first name, last name and email from Keycloak using Quarkus OIDC integration

When I access the /openid-connect/token endpoint using admin_cli client_id I can see more/different info in the payload of returned access_token compared to when token is injected into my bean by the Quarkus OIDC/Keycloak extension.
Here are some samples:
{
"exp": 1671084133,
"iat": 1671083533,
"jti": "b95bac0a-f95e-413d-b2cd-3b97fcf5f3c8",
"iss": "http://localhost:51521/realms/my-realm",
"sub": "cda64011-47a8-4a6a-8aac-06c7db6fc593",
"typ": "Bearer",
"azp": "admin-cli",
"session_state": "be12a28b-4143-4bbf-9914-c8454d93f50f",
"acr": "1",
"scope": "profile email",
"sid": "be12a28b-4143-4bbf-9914-c8454d93f50f",
"email_verified": false,
"preferred_username": "test",
"given_name": "vasia",
"family_name": "pupkin",
"email": "test#test.com"
}
Versus
{
"exp": 1671086253,
"iat": 1671085653,
"auth_time": 1671085653,
"jti": "05e9f66d-54a1-440b-9295-3ebd681a853a",
"iss": "http://localhost:51521/realms/my-realm",
"sub": "cda64011-47a8-4a6a-8aac-06c7db6fc593",
"typ": "Bearer",
"azp": "my-app",
"session_state": "ba00821c-1556-4214-90d7-5f2a55b0074a",
"scope": "openid microprofile-jwt",
"sid": "ba00821c-1556-4214-90d7-5f2a55b0074a",
"upn": "test",
"groups": [
"offline_access",
"admin",
"uma_authorization",
"default-roles-collar-club"
]
}
I'm interested in still getting the groups (for role based access) and given_name, family_name, email properties as well in my Quarkus app.
Tried to specify: quarkus.oidc.authentication.scopes=openid,profile,groups - getting error in the url redirected from Keycloak:
2022-12-14 23:11:19,984 DEBUG [io.qua.oid.run.CodeAuthenticationMechanism] (vert.x-eventloop-thread-2) Authentication has failed, error: invalid_scope, description: Invalid scopes: openid openid profile groups
openid is always added by Quarkus, Keycloak does not like duplicate scope values, so remove openid

How to get the roles in Auth0's user management to be added in the JWT?

I have an Auth0 application and I'm maintaining roles through the User Management. I would like to get those roles that are assigned to a user to be added to the JWT returned.
I do have the following in the openid_connect_configuration.conf
map $host $oidc_scopes {
default "openid+profile+email+offline_access+openid roles";
}
i have the following in the /.well-known/openid-configuration
{
...
"scopes_supported": [
"openid",
"profile",
"offline_access",
"name",
"given_name",
"family_name",
"nickname",
"email",
"email_verified",
"picture",
"created_at",
"identities",
"phone",
"address"
],
"response_types_supported": [
"code",
"token",
"id_token",
"code token",
"code id_token",
"token id_token",
"code token id_token"
],
"code_challenge_methods_supported": [
"S256",
"plain"
],
"response_modes_supported": [
"query",
"fragment",
"form_post"
],
"subject_types_supported": ["public"],
"id_token_signing_alg_values_supported": [
"HS256",
"RS256"
],
"token_endpoint_auth_methods_supported": [
"client_secret_basic",
"client_secret_post"
],
"claims_supported": [
"aud",
"auth_time",
"created_at",
"email",
"email_verified",
"exp",
"family_name",
"given_name",
"iat",
"identities",
"iss",
"name",
"nickname",
"phone_number",
"picture",
"sub"
],
"request_uri_parameter_supported": false
}
How do I set things in Auth0 to return the roles assigned to the logged in user? I have tried looking into the documentation, but I had no luck.
I found my answer through exploring the extensions in Auth0. I installed the Auth0 Authorization extension. I enabled the groups and roles.
I then added the following rule:
function setRolesToUser(user, context, callback) {
// Roles should only be set to verified users.
if (!user.email || !user.email_verified) {
return callback(null, user, context);
}
user.app_metadata = user.app_metadata || {};
auth0.users
.updateAppMetadata(user.user_id, user.app_metadata)
.then(function () {
context.idToken['https://example.com/auth'] = user.app_metadata.authorization;
callback(null, user, context);
})
.catch(function (err) {
callback(err);
});
}
I get the following as the JWT payload:
{
"https://example.com/auth": {
"groups": ["Samples"],
"roles": ["Editor"]
},
"sub": "auth0|xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"nickname": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"email_verified": true,
"iss": "https://dev-xxxxxxxxxx.us.auth0.com/",
"updated_at": "2022-04-29T20:01:14.585Z",
"iat": 1.651330616E9,
"picture": "https://s.gravatar.com/avatar/a705adb3d5d8530c35c41a9de260cd3c?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Flo.png",
"exp": 1.651366616E9,
"name": "xxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxx",
"aud": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"nonce": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"email": "xxxxx.xxxxxxxxx#example.com"
}

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

Keycloak Bear-Only Client with and without Authorization Client Secret

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.

What are Keycloak's OAuth2 / OpenID Connect endpoints?

We are trying to evaluate Keycloak as an SSO solution, and it looks good in many respects, but the documentation is painfully lacking in the basics.
For a given Keycloak installation on http://localhost:8080/ for realm test, what are the OAuth2 Authorization Endpoint, OAuth2 Token Endpoint and OpenID Connect UserInfo Endpoint ?
We are not interested in using Keycloak's own client library, we want to use standard OAuth2 / OpenID Connect client libraries, as the client applications using the keycloak server will be written in a wide range of languages (PHP, Ruby, Node, Java, C#, Angular). Therefore the examples that use the Keycloak client aren't of use for us.
For Keycloak 1.2 the above information can be retrieved via the url
http://keycloakhost:keycloakport/auth/realms/{realm}/.well-known/openid-configuration
For example, if the realm name is demo:
http://keycloakhost:keycloakport/auth/realms/demo/.well-known/openid-configuration
An example output from above url:
{
"issuer": "http://localhost:8080/auth/realms/demo",
"authorization_endpoint": "http://localhost:8080/auth/realms/demo/protocol/openid-connect/auth",
"token_endpoint": "http://localhost:8080/auth/realms/demo/protocol/openid-connect/token",
"userinfo_endpoint": "http://localhost:8080/auth/realms/demo/protocol/openid-connect/userinfo",
"end_session_endpoint": "http://localhost:8080/auth/realms/demo/protocol/openid-connect/logout",
"jwks_uri": "http://localhost:8080/auth/realms/demo/protocol/openid-connect/certs",
"grant_types_supported": [
"authorization_code",
"refresh_token",
"password"
],
"response_types_supported": [
"code"
],
"subject_types_supported": [
"public"
],
"id_token_signing_alg_values_supported": [
"RS256"
],
"response_modes_supported": [
"query"
]
}
Found information at https://issues.jboss.org/browse/KEYCLOAK-571
Note: You might need to add your client to the Valid Redirect URI list
Actually link to .well-known is on the first tab of your realm settings - but link doesn't look like link, but as value of text box... bad ui design.
Screenshot of Realm's General Tab
You can also see this information by going into Admin Console -> Realm Settings -> Clicking the hyperlink on the Endpoints field.
I'm currently experimenting with Keycloak 18.0.0, and I found that the "/auth" part is removed from the OIDC discovery URL:
https://{keycloakhost}:{keycloakport}/realms/{realm}/.well-known/openid-configuration
This returns a JSON data structure that contains the endpoints:
{
"issuer": "https://{keycloakhost}:{keycloakport}/realms/{realm}",
"authorization_endpoint": "https://{keycloakhost}:{keycloakport}/realms/{realm}/protocol/openid-connect/auth",
"token_endpoint": "https://{keycloakhost}:{keycloakport}/realms/{realm}/protocol/openid-connect/token",
"introspection_endpoint": "https://{keycloakhost}:{keycloakport}/realms/{realm}/protocol/openid-connect/token/introspect",
"userinfo_endpoint": "https://{keycloakhost}:{keycloakport}/realms/{realm}/protocol/openid-connect/userinfo",
"end_session_endpoint": "https://{keycloakhost}:{keycloakport}/realms/{realm}/protocol/openid-connect/logout",
"frontchannel_logout_session_supported": true,
"frontchannel_logout_supported": true,
"jwks_uri": "https://{keycloakhost}:{keycloakport}/realms/{realm}/protocol/openid-connect/certs",
"check_session_iframe": "https://{keycloakhost}:{keycloakport}/realms/{realm}/protocol/openid-connect/login-status-iframe.html",
"grant_types_supported": [
"authorization_code",
"implicit",
"refresh_token",
"password",
"client_credentials",
"urn:ietf:params:oauth:grant-type:device_code",
"urn:openid:params:grant-type:ciba"
],
"response_types_supported": [
"code",
"none",
"id_token",
"token",
"id_token token",
"code id_token",
"code token",
"code id_token token"
],
"subject_types_supported": [
"public",
"pairwise"
],
"id_token_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512"
],
"id_token_encryption_alg_values_supported": [
"RSA-OAEP",
"RSA-OAEP-256",
"RSA1_5"
],
"id_token_encryption_enc_values_supported": [
"A256GCM",
"A192GCM",
"A128GCM",
"A128CBC-HS256",
"A192CBC-HS384",
"A256CBC-HS512"
],
"userinfo_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512",
"none"
],
"request_object_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512",
"none"
],
"request_object_encryption_alg_values_supported": [
"RSA-OAEP",
"RSA-OAEP-256",
"RSA1_5"
],
"request_object_encryption_enc_values_supported": [
"A256GCM",
"A192GCM",
"A128GCM",
"A128CBC-HS256",
"A192CBC-HS384",
"A256CBC-HS512"
],
"response_modes_supported": [
"query",
"fragment",
"form_post",
"query.jwt",
"fragment.jwt",
"form_post.jwt",
"jwt"
],
"registration_endpoint": "https://{keycloakhost}:{keycloakport}/realms/{realm}/clients-registrations/openid-connect",
"token_endpoint_auth_methods_supported": [
"private_key_jwt",
"client_secret_basic",
"client_secret_post",
"tls_client_auth",
"client_secret_jwt"
],
"token_endpoint_auth_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512"
],
"introspection_endpoint_auth_methods_supported": [
"private_key_jwt",
"client_secret_basic",
"client_secret_post",
"tls_client_auth",
"client_secret_jwt"
],
"introspection_endpoint_auth_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512"
],
"authorization_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512"
],
"authorization_encryption_alg_values_supported": [
"RSA-OAEP",
"RSA-OAEP-256",
"RSA1_5"
],
"authorization_encryption_enc_values_supported": [
"A256GCM",
"A192GCM",
"A128GCM",
"A128CBC-HS256",
"A192CBC-HS384",
"A256CBC-HS512"
],
"claims_supported": [
"aud",
"sub",
"iss",
"auth_time",
"name",
"given_name",
"family_name",
"preferred_username",
"email",
"acr"
],
"claim_types_supported": [
"normal"
],
"claims_parameter_supported": true,
"scopes_supported": [
"openid",
"phone",
"roles",
"microprofile-jwt",
"email",
"web-origins",
"offline_access",
"address",
"profile"
],
"request_parameter_supported": true,
"request_uri_parameter_supported": true,
"require_request_uri_registration": true,
"code_challenge_methods_supported": [
"plain",
"S256"
],
"tls_client_certificate_bound_access_tokens": true,
"revocation_endpoint": "https://{keycloakhost}:{keycloakport}/realms/{realm}/protocol/openid-connect/revoke",
"revocation_endpoint_auth_methods_supported": [
"private_key_jwt",
"client_secret_basic",
"client_secret_post",
"tls_client_auth",
"client_secret_jwt"
],
"revocation_endpoint_auth_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512"
],
"backchannel_logout_supported": true,
"backchannel_logout_session_supported": true,
"device_authorization_endpoint": "https://{keycloakhost}:{keycloakport}/realms/{realm}/protocol/openid-connect/auth/device",
"backchannel_token_delivery_modes_supported": [
"poll",
"ping"
],
"backchannel_authentication_endpoint": "https://{keycloakhost}:{keycloakport}/realms/{realm}/protocol/openid-connect/ext/ciba/auth",
"backchannel_authentication_request_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"ES256",
"RS256",
"ES512",
"PS256",
"PS512",
"RS512"
],
"require_pushed_authorization_requests": false,
"pushed_authorization_request_endpoint": "https://{keycloakhost}:{keycloakport}/realms/{realm}/protocol/openid-connect/ext/par/request",
"mtls_endpoint_aliases": {
"token_endpoint": "https://{keycloakhost}:{keycloakport}/realms/{realm}/protocol/openid-connect/token",
"revocation_endpoint": "https://{keycloakhost}:{keycloakport}/realms/{realm}/protocol/openid-connect/revoke",
"introspection_endpoint": "https://{keycloakhost}:{keycloakport}/realms/{realm}/protocol/openid-connect/token/introspect",
"device_authorization_endpoint": "https://{keycloakhost}:{keycloakport}/realms/{realm}/protocol/openid-connect/auth/device",
"registration_endpoint": "https://{keycloakhost}:{keycloakport}/realms/{realm}/clients-registrations/openid-connect",
"userinfo_endpoint": "https://{keycloakhost}:{keycloakport}/realms/{realm}/protocol/openid-connect/userinfo",
"pushed_authorization_request_endpoint": "https://{keycloakhost}:{keycloakport}/realms/{realm}/protocol/openid-connect/ext/par/request",
"backchannel_authentication_endpoint": "https://{keycloakhost}:{keycloakport}/realms/{realm}/protocol/openid-connect/ext/ciba/auth"
}
}
With version 1.9.3.Final, Keycloak has a number of OpenID endpoints available. These can be found at /auth/realms/{realm}/.well-known/openid-configuration. Assuming your realm is named demo, that endpoint will produce a JSON response similar to this.
{
"issuer": "http://localhost:8080/auth/realms/demo",
"authorization_endpoint": "http://localhost:8080/auth/realms/demo/protocol/openid-connect/auth",
"token_endpoint": "http://localhost:8080/auth/realms/demo/protocol/openid-connect/token",
"token_introspection_endpoint": "http://localhost:8080/auth/realms/demo/protocol/openid-connect/token/introspect",
"userinfo_endpoint": "http://localhost:8080/auth/realms/demo/protocol/openid-connect/userinfo",
"end_session_endpoint": "http://localhost:8080/auth/realms/demo/protocol/openid-connect/logout",
"jwks_uri": "http://localhost:8080/auth/realms/demo/protocol/openid-connect/certs",
"grant_types_supported": [
"authorization_code",
"implicit",
"refresh_token",
"password",
"client_credentials"
],
"response_types_supported": [
"code",
"none",
"id_token",
"token",
"id_token token",
"code id_token",
"code token",
"code id_token token"
],
"subject_types_supported": [
"public"
],
"id_token_signing_alg_values_supported": [
"RS256"
],
"response_modes_supported": [
"query",
"fragment",
"form_post"
],
"registration_endpoint": "http://localhost:8080/auth/realms/demo/clients-registrations/openid-connect"
}
As far as I have found, these endpoints implement the Oauth 2.0 spec.
After much digging around we were able to scrape the info more or less (mainly from Keycloak's own JS client lib):
Authorization Endpoint: /auth/realms/{realm}/tokens/login
Token Endpoint: /auth/realms/{realm}/tokens/access/codes
As for OpenID Connect UserInfo, right now (1.1.0.Final) Keycloak doesn't implement this endpoint, so it is not fully OpenID Connect compliant. However, there is already a patch that adds that as of this writing should be included in 1.2.x.
But - Ironically Keycloak does send back an id_token in together with the access token. Both the id_token and the access_token are signed JWTs, and the keys of the token are OpenID Connect's keys, i.e:
"iss": "{realm}"
"sub": "5bf30443-0cf7-4d31-b204-efd11a432659"
"name": "Amir Abiri"
"email: "..."
So while Keycloak 1.1.x is not fully OpenID Connect compliant, it does "speak" in OpenID Connect language.
In version 1.9.0 json with all endpoints is at address /auth/realms/{realm}
Authorization Endpoint: /auth/realms/{realm}/account
Token Endpoint: /auth/realms/{realm}/protocol/openid-connect
Following link Provides JSON document describing metadata about the Keycloak
/auth/realms/{realm-name}/.well-known/openid-configuration
Following information reported with Keycloak 6.0.1 for master realm
{
"issuer":"http://localhost:8080/auth/realms/master",
"authorization_endpoint":"http://localhost:8080/auth/realms/master/protocol/openid-connect/auth",
"token_endpoint":"http://localhost:8080/auth/realms/master/protocol/openid-connect/token",
"token_introspection_endpoint":"http://localhost:8080/auth/realms/master/protocol/openid-connect/token/introspect",
"userinfo_endpoint":"http://localhost:8080/auth/realms/master/protocol/openid-connect/userinfo",
"end_session_endpoint":"http://localhost:8080/auth/realms/master/protocol/openid-connect/logout",
"jwks_uri":"http://localhost:8080/auth/realms/master/protocol/openid-connect/certs",
"check_session_iframe":"http://localhost:8080/auth/realms/master/protocol/openid-connect/login-status-iframe.html",
"grant_types_supported":[
"authorization_code",
"implicit",
"refresh_token",
"password",
"client_credentials"
],
"response_types_supported":[
"code",
"none",
"id_token",
"token",
"id_token token",
"code id_token",
"code token",
"code id_token token"
],
"subject_types_supported":[
"public",
"pairwise"
],
"id_token_signing_alg_values_supported":[
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512"
],
"userinfo_signing_alg_values_supported":[
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512",
"none"
],
"request_object_signing_alg_values_supported":[
"PS384",
"ES384",
"RS384",
"ES256",
"RS256",
"ES512",
"PS256",
"PS512",
"RS512",
"none"
],
"response_modes_supported":[
"query",
"fragment",
"form_post"
],
"registration_endpoint":"http://localhost:8080/auth/realms/master/clients-registrations/openid-connect",
"token_endpoint_auth_methods_supported":[
"private_key_jwt",
"client_secret_basic",
"client_secret_post",
"client_secret_jwt"
],
"token_endpoint_auth_signing_alg_values_supported":[
"RS256"
],
"claims_supported":[
"aud",
"sub",
"iss",
"auth_time",
"name",
"given_name",
"family_name",
"preferred_username",
"email"
],
"claim_types_supported":[
"normal"
],
"claims_parameter_supported":false,
"scopes_supported":[
"openid",
"address",
"email",
"microprofile-jwt",
"offline_access",
"phone",
"profile",
"roles",
"web-origins"
],
"request_parameter_supported":true,
"request_uri_parameter_supported":true,
"code_challenge_methods_supported":[
"plain",
"S256"
],
"tls_client_certificate_bound_access_tokens":true,
"introspection_endpoint":"http://localhost:8080/auth/realms/master/protocol/openid-connect/token/introspect"
}
keycloak version: 4.6.0
TokenUrl: [domain]/auth/realms/{REALM_NAME}/protocol/openid-connect/token
AuthUrl: [domain]/auth/realms/{REALM_NAME}/protocol/openid-connect/auth
For Hostname Endpoints:
https://keycloak.{HOSTNAME}/realms/{REALM}/.well-known/openid-configuration
FQDN/auth/realms/{realm_name}/.well-known/openid-configuration
you will see everything here, plus if the identity provider is also Keycloak then feeding this URL will setup everything also true with other identity providers if they support and they already handled it
TL;DR:
KC below 18.0.0: https://${hostname}/auth/realms/${realm}/.well-known/openid-configuration
KC 18.0.0 and up: https://${hostname}/realms/${realm}/.well-known/openid-configuration
A more in depth explanation. According to the openid-connect standard
Obtaining OpenID Provider Configuration Information
Using the Issuer location discovered (...) the OpenID Provider's configuration information can be
retrieved.
OpenID Providers supporting Discovery MUST make a JSON document
available at the path formed by concatenating the string
/.well-known/openid-configuration to the Issuer. (..)
So according to the standard the endpoint is on ${issuer_url}/.well-known/openid-configuration.
For Keycloak versions before 18.0.0:
The issuer is https://${host}:${port}/auth/realms/${realm}/ so the openid-configuration is on:
https://${host}:${port}/auth/realms/${realm}/.well-known/openid-configuration
Or via UI:
Go to your realm, then realm settings:
and then click on OpenID Endpoint Configuration.
For Keycloak version 18.0.0 and onwards (auth was removed)
The issuer is https://${host}:${port}/realms/${realm}/ so the openid-configuration is on:
https://${host}:${port}/realms/${realm}/.well-known/openid-configuration
Go to your realm, then realm settings:
and then click on OpenID Endpoint Configuration.