diff --git a/Docker/Multiplied.json b/Docker/Multiplied.json index 05e6264..ca91817 100644 --- a/Docker/Multiplied.json +++ b/Docker/Multiplied.json @@ -380,20 +380,20 @@ "webAuthnPolicyPasswordlessExtraOrigins" : [ ], "users" : [ { "id" : "208788ad-c74a-4c65-9ddb-864ea541b7c3", - "username" : "cvillaronga", - "firstName" : "Carlos", - "lastName" : "Villaronga", - "email" : "cvillaronga+1@multiplied.com", + "username" : "johndoe", + "firstName" : "John", + "lastName" : "Doe", + "email" : "johndoe@example.com", "emailVerified" : true, "createdTimestamp" : 1730478248831, "enabled" : true, "totp" : false, "credentials" : [ { - "id" : "8e2280d3-8476-43c7-9ab5-8ed859a97986", + "id" : "87654321-abcd-43c7-9ab5-8ed859a97986", "type" : "password", "userLabel" : "My password", - "createdDate" : 1730478277298, - "secretData" : "{\"value\":\"RiOuJAc7g2R49iMwzaajoAfVm2RZxHUcQ36EC8JalHA=\",\"salt\":\"LdE5JsNcwfXKEIyw/fKeKg==\",\"additionalParameters\":{}}", + "createdDate" : 1731094275423, + "secretData" : "{\"value\":\"nrs0YPXNOwrX0mkflqpy+eZjMNEUEMs3egnKDXS/xbo=\",\"salt\":\"BP6xOuNh6BwxrUHopZuTMg==\",\"additionalParameters\":{}}", "credentialData" : "{\"hashIterations\":5,\"algorithm\":\"argon2\",\"additionalParameters\":{\"hashLength\":[\"32\"],\"memory\":[\"7168\"],\"type\":[\"id\"],\"version\":[\"1.3\"],\"parallelism\":[\"1\"]}}" } ], "disableableCredentialTypes" : [ ], @@ -406,6 +406,10 @@ }, "notBefore" : 0, "groups" : [ ] + } ], + "scopeMappings" : [ { + "clientScope" : "offline_access", + "roles" : [ "offline_access" ] }, { "id" : "ccb4aee3-ec17-411c-80b6-9febb88fae4e", "username" : "service-account-keycloakintegration", @@ -421,10 +425,6 @@ "notBefore" : 0, "groups" : [ ] } ], - "scopeMappings" : [ { - "clientScope" : "offline_access", - "roles" : [ "offline_access" ] - } ], "clientScopeMappings" : { "account" : [ { "client" : "account-console", @@ -452,8 +452,8 @@ "standardFlowEnabled" : true, "implicitFlowEnabled" : false, "directAccessGrantsEnabled" : true, - "serviceAccountsEnabled" : true, - "publicClient" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, "frontchannelLogout" : true, "protocol" : "openid-connect", "attributes" : { @@ -463,6 +463,7 @@ "backchannel.logout.session.required" : "true", "post.logout.redirect.uris" : "+", "oauth2.device.authorization.grant.enabled" : "false", + "display.on.consent.screen" : "false", "backchannel.logout.revoke.offline.tokens" : "false", "client.secret.expiration" : "0" }, @@ -864,8 +865,9 @@ "included.client.audience" : "KeyCloakIntegration", "id.token.claim" : "false", "lightweight.claim" : "false", + "introspection.token.claim" : "true", "access.token.claim" : "true", - "introspection.token.claim" : "true" + "userinfo.token.claim" : "false" } } ] }, { @@ -1349,7 +1351,7 @@ "subType" : "anonymous", "subComponents" : { }, "config" : { - "allowed-protocol-mapper-types" : [ "oidc-address-mapper", "oidc-full-name-mapper", "oidc-usermodel-attribute-mapper", "oidc-usermodel-property-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-attribute-mapper", "saml-user-property-mapper", "saml-role-list-mapper" ] + "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "saml-user-property-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-role-list-mapper", "oidc-usermodel-attribute-mapper", "saml-user-attribute-mapper", "oidc-address-mapper", "oidc-full-name-mapper" ] } }, { "id" : "0840bfc1-bd47-49c7-b44c-f10e4d311edd", @@ -1365,7 +1367,7 @@ "subType" : "authenticated", "subComponents" : { }, "config" : { - "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "oidc-full-name-mapper", "oidc-usermodel-attribute-mapper", "oidc-address-mapper", "saml-user-property-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-role-list-mapper", "saml-user-attribute-mapper" ] + "allowed-protocol-mapper-types" : [ "oidc-usermodel-attribute-mapper", "oidc-full-name-mapper", "saml-user-property-mapper", "saml-role-list-mapper", "oidc-usermodel-property-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-attribute-mapper", "oidc-address-mapper" ] } }, { "id" : "dbbca22a-769f-401a-a8b7-7a9a3f098df9", diff --git a/README.md b/README.md index a4342f8..7796c48 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,8 @@ For full development capabilities, it is recommended to use Visual Studio on Win 1. user name and password for Keycloak can be edited form the [env file](/Docker/env) 1. Keycloak version can be updated from the [env file](/Docker/env) 1. Seed Realm, Clients and Users can be edited from the [realm json file](/Docker/Multiplied.json) or a different json file can be reference from the [env file](/Docker/env) -1. Log in into [Keycloak](http://localhost:8080/admin) -1. Navigate to [app](http://localhost:8081/) +1. Log in into [Keycloak](http://localhost:8080/admin) Use the user **admin** password **admin** +1. Navigate to [app](http://localhost:8081/), In order to login in the app use the user **johndoe** password **jhondoe123** # GitHub Actions @@ -57,6 +57,34 @@ Currently, the following workflows are active: These CI workflows are essential for maintaining project health, ensuring that code changes are reliable, and providing a strong foundation for future development. + +### Creating a Client in a Keycloak Realm + +To set up a client in Keycloak, follow these steps to create either a Machine-to-Machine (M2M) client or a standard user-facing client with regular login functionality. + +#### Steps to Create a Client + +1. **Access the Keycloak Admin Console**: Navigate to your Keycloak admin console and select the desired realm. + +1. **Create a New Client**: + - Go to **Clients** in the sidebar. + - Click **Create** and provide a unique **Client ID**. Choose a descriptive name to indicate the client’s purpose (e.g., "MyAppAPI" for M2M, "MyAppWeb" for user logins). + +#### Machine-to-Machine (M2M) Clients + +Machine-to-machine clients are used for server-to-server communication, where the client authenticates using its credentials rather than relying on a user login flow. The setup includes enabling client authentication and specifying the audience scope. + +1. **Client Authentication**: Under the **Settings** tab, make sure that **Service Accounts Enabled** is set to **ON**. This will allow the client to authenticate itself using client credentials (e.g., client ID and secret). +1. **Scope & Audience:** Define the required audience and specify the scopes that this client can access within your application. Follow the steps [## How to create an audience] + +#### Regular Login Clients + +For user-facing clients, such as web applications, the primary configuration involves enabling browser-based authentication without client credentials or specialized audience scopes. + +1. **Disable Client Authentication**: + - Since users log in directly, there is no need for the client to authenticate itself. **Service Accounts Enabled** should be set to **OFF**. + + ## How to create an audience An audience in Keycloak is a specific identifier that can be included in access tokens. This allows you to control which services or applications can accept a particular token, enhancing security and fine-grained access control. @@ -75,19 +103,21 @@ To create an audience for a client in Keycloak, which we’ll call `untrusted-au 1. Click **Client Scopes** tab. 1. Click **Create Client Scopes** to add a new client scope. 1. Give it a name, e.g., `untrusted-audience`. -1. Select OpenID Connect as the client protocol. 1. Set Type to `Optional`. ### Step 4: Create an Audience Mapper: - - Go to the **Mappers** tab of your client. - - Click **Create**. - - Select **Mapper Type** as **Audience**. + - Go to the **Mappers** tab of your client scope. + - Click **Configure a new mapper**. + - Select **Audience**. + - Complete your audience **Name**. - In the **Included Custom Audience** field, enter the desired audience value, such as `your-api-endpoint`. - Enable the **Add to Access Token** checkbox. ### Step 5: **Assign the Client Scope to Your Client: + - Go to the **Clients** list. + - Select **Your Client ID**. - Go to the **Client Scopes** tab of your client. - - Add the newly created client scope (`api-audience`) to your client. + - Add the newly created client scope ()`untrusted-audience`) to your client. **Understanding the Process:**