421.3 Abp microserices and Keycloak - chempkovsky/CS82ANGULAR GitHub Wiki

Notes

  • Only security aspects will be discussed and implemented.
  • In this article we will configure Keycloak

Tools

New realm

  • In keycloak console
    • click Manage realms-menu
      • click Create realm-button
  • In the Create realm-dialog
    • Realm name: rupbes.tstrealm
    • Enabled: ON
    • click Create-button

User profile

  • In keycloak console
    • click Manage realms-menu
    • click rupbes.tstrealm
    • click Realm settings
    • click User profile-tab
    • On the Attributes-tab click Create Attribute-button
  • On the Create attribute-page
    • Attribute [Name]: tenantid
    • Who can edit?: Admin
    • Who can view?: Admin, User
    • Enabled when: Always
    • Attribute group: None
    • click Create-button

New user

  • In keycloak console
    • click Manage realms-menu
    • click rupbes.tstrealm
    • click Users-menu
    • click Create New User-button
  • On the Create user-page
    • Username: tstadmin
    • tenantid: HOST
    • Email verified: ON
    • Email: [email protected]
    • First name: tstadminFN
    • Last name: tstadminLN
  • On the tstadmin-page
    • click Credetentials-tab
    • click Set password-button
    • In the Set password for tstadmin-dialog
      • Enter password
      • Temporary: OFF
      • click Save-button
  • On the tstadmin-page
    • copy ID into clipboard (in our case it is 5d10b343-a3e3-40a4-82e2-9e30efb658f7)
  • Open HostHttpApiHostModule.cs-file of the rupbes.tstapp.Auth.Host.csproj-project
    • modify SeedData()-method as follows:
Click to show the code
    private async Task SeedData(ApplicationInitializationContext context)
    {
        using (var scope = context.ServiceProvider.CreateScope())
        {
            var seeder = scope.ServiceProvider
                .GetRequiredService<IDataSeeder>();
            await seeder.SeedAsync(
                new DataSeedContext()
                .WithProperty("AdminId", new Guid("5d10b343-a3e3-40a4-82e2-9e30efb658f7")) // your ID of the created keycloak user
                .WithProperty("AdminEmail", "[email protected]") // your Email of the created keycloak user
                .WithProperty("AdminUserName", "tstadmin") // your UserName of the created keycloak user
                // .WithProperty("AdminPassword", "1q2w3E*") // it doesn't matter what password is set
                );
        }
    }

tstwebapp

  • open the Properties/launchSettings.json-file of the rupbes.tstapp.Web.Host.csproj-project and copy the value of the "profiles/rupbes.tstapp.Web.Host/applicationUrl"-prop. In our case it is "https://localhost:44377".
  • In keycloak console
    • click Manage realms-menu
    • click rupbes.tstrealm
    • click Clients-menu
    • click Create Client-button
  • On the Create client-page
    • Client type: OpenID Connect
    • Client ID: tstwebapp
    • Client authentication: ON
    • Authorization: OFF
    • Authentication flow: Standard flow
    • Root URL: https://localhost:44377 (we copied this value from Properties/launchSettings.json-file above)
    • Home URL: https://localhost:44377 (we copied this value from Properties/launchSettings.json-file above)
    • Web origins: https://localhost:44377 (we copied this value from Properties/launchSettings.json-file above)
    • Valid redirect URIs: /signin-oidc
    • Valid post logout redirect URIs: /signout-callback-oidc
    • click Save-button
  • On the tstwebapp-page
    • click Credetentials-tab
    • copy Client Secret-value into the clipboard. In our case it is LmmU7nynLQR0nsnN6shOw3sGFfatKqvP
  • Open appsettings.json of the rupbes.tstapp.Web.Host.csproj-project and modify as follows:
    • the value for the "RemoteServices/Default/BaseUrl" we copied from Properties/launchSettings.json-file of the rupbes.tstapp.Auth.Host.csproj-project
    • Set correct value for "Redis/Configuration". In our case we use 10.183.96.52:6379
    • Set correct protocol(http/https), host and port of your keycloak server. In our case it is https://kc.rupbes.by:8445
    • Set correct value for "AuthServer/RequireHttpsMetadata". In our case we use Https.
    • the value for "AuthServer/ClientSecret"-prop we copied above
Click to show the code
{
  "App": {
    "SelfUrl": "https://localhost:44377/"
  },
  "RemoteServices": {
    "Default": {
      "BaseUrl": "https://localhost:54635/"
    },
    "tstapp": {
      "BaseUrl": "https://localhost:44323/"
    }
  },
  "Redis": {
    "Configuration": "10.183.96.52:6379,user=your_user_name_here,password=your_password_name_here"
  },

  "AuthServer": {
    "Authority": "https://kc.rupbes.by:8445/realms/rupbes.tstrealm",
    "MetaAddress": "https://kc.rupbes.by:8445/realms/rupbes.tstrealm/.well-known/openid-configuration",
    "Configuration": "https://kc.rupbes.by:8445/realms/rupbes.tstrealm/.well-known/openid-configuration",
    "RequireHttpsMetadata": true,
    "ClientId": "tstwebapp",
    "ClientSecret": "LmmU7nynLQR0nsnN6shOw3sGFfatKqvP"
  }
}

tstauth

  • open the Properties/launchSettings.json-file of the rupbes.tstapp.Auth.Host.csproj-project and copy the value of the "profiles/rupbes.tstapp.Auth.Host/applicationUrl"-prop. In our case it is "https://localhost:54635".
  • In keycloak console
    • click Manage realms-menu
    • click rupbes.tstrealm
    • click Clients-menu
    • click Create Client-button
  • On the Create client-page
    • Client type: OpenID Connect
    • Client ID: tstauth
    • Client authentication: ON
    • Authorization: OFF
    • Authentication flow: Standard flow
    • Root URL: https://localhost:54635 (we copied this value from Properties/launchSettings.json-file above)
    • Home URL: https://localhost:54635 (we copied this value from Properties/launchSettings.json-file above)
    • Web origins: https://localhost:54635 (we copied this value from Properties/launchSettings.json-file above)
    • Valid redirect URIs: (did not set, i.e. empty)
    • Valid post logout redirect URIs: (did not set, i.e. empty)
    • click Save-button
  • Open appsettings.json of the rupbes.tstapp.Auth.Host.csproj-project and modify as follows:
    • Set correct value for "Redis/Configuration". In our case we use 10.183.96.52:6379
    • Set correct protocol(http/https), host and port of your keycloak server. In our case it is https://kc.rupbes.by:8445
    • Set correct value for "AuthServer/RequireHttpsMetadata". In our case we use Https.
    • the value for "App/CorsOrigins"-prop we copied from appsettings.json of the rupbes.tstapp.HttpApi.Host.csproj-project
    • the value for "ConnectionStrings"-prop we copied from appsettings.json of the rupbes.tstapp.HttpApi.Host.csproj-project (we copied only "Default" connection string)
    • "AuthServer/SwaggerClientId" and "AuthServer/SwaggerClientSecret" are incorrect for now (because we didn't register it in keycloak and we didn't tested it !!!)
Click to show the code
{
  "App": {
    "CorsOrigins": "https://*.tstapp.com,http://localhost:4200,http://localhost:44307,https://localhost:44307"
  },
  "ConnectionStrings": {
    "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=tstapp_Main;Trusted_Connection=True;TrustServerCertificate=True"
  },
  "Redis": {
    "Configuration": "10.183.96.52:6379,user=your_user_name_here,password=your_password_name_here"
  },
  "AuthServer": {
    "Issuer": "https://kc.rupbes.by:8445/realms/rupbes.tstrealm",
    "Authority": "https://kc.rupbes.by:8445/realms/rupbes.tstrealm/protocol/openid-connect/",
    "MetaAddress": "https://kc.rupbes.by:8445/realms/rupbes.tstrealm/.well-known/openid-configuration",
    "Configuration": "https://kc.rupbes.by:8445/realms/rupbes.tstrealm/.well-known/openid-configuration",
    "Audience": "tstauth",
    "RequireHttpsMetadata": true,
    "SwaggerClientId": "tstauth_Swagger",
    "SwaggerClientSecret": "1q2w3e*"
  }
}

tstapihost

  • open the Properties/launchSettings.json-file of the rupbes.tstapp.HttpApi.Host.csproj-project and copy the value of the "profiles/rupbes.tstapp.DemoApp/applicationUrl"-prop. In our case it is "https://localhost:44323".
  • In keycloak console
    • click Manage realms-menu
    • click rupbes.tstrealm
    • click Clients-menu
    • click Create Client-button
  • On the Create client-page
    • Client type: OpenID Connect
    • Client ID: tstapihost
    • Client authentication: ON
    • Authorization: OFF
    • Authentication flow: Standard flow
    • Root URL: https://localhost:44323 (we copied this value from Properties/launchSettings.json-file above)
    • Home URL: https://localhost:44323 (we copied this value from Properties/launchSettings.json-file above)
    • Web origins: https://localhost:44323 (we copied this value from Properties/launchSettings.json-file above)
    • Valid redirect URIs: (did not set, i.e. empty)
    • Valid post logout redirect URIs: (did not set, i.e. empty)
    • click Save-button
  • Open appsettings.json of the rupbes.tstapp.HttpApi.Host.csproj-project and modify as follows:
    • Set correct value for "Redis/Configuration". In our case we use 10.183.96.52:6379
    • Set correct protocol(http/https), host and port of your keycloak server. In our case it is https://kc.rupbes.by:8445
    • Set correct value for "AuthServer/RequireHttpsMetadata". In our case we use Https.
    • the value for "App/CorsOrigins"-prop was generated by abp.cli
    • the value for "ConnectionStrings"-prop was generated by abp.cli
    • "AuthServer/SwaggerClientId" and "AuthServer/SwaggerClientSecret" are incorrect for now (because we didn't register it in keycloak and we didn't tested it !!!)
Click to show the code
{
  "App": {
    "CorsOrigins": "https://*.tstapp.com,http://localhost:4200,http://localhost:44307,https://localhost:44307"
  },
  "ConnectionStrings": {
    "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=tstapp_Main;Trusted_Connection=True;TrustServerCertificate=True",
    "tstapp": "Server=(LocalDb)\\MSSQLLocalDB;Database=tstapp_Module;Trusted_Connection=True;TrustServerCertificate=True"
  },
  "Redis": {
    "Configuration": "10.183.96.52:6379,user=your_user_name_here,password=your_password_name_here"
  },
  "AuthServer": {
    "Issuer": "https://kc.rupbes.by:8445/realms/rupbes.tstrealm",
    "Authority": "https://kc.rupbes.by:8445/realms/rupbes.tstrealm/protocol/openid-connect/",
    "MetaAddress": "https://kc.rupbes.by:8445/realms/rupbes.tstrealm/.well-known/openid-configuration",
    "Configuration": "https://kc.rupbes.by:8445/realms/rupbes.tstrealm/.well-known/openid-configuration",
    "Audience": "tstapihost",
    "RequireHttpsMetadata": true,
    "SwaggerClientId": "tstapihost_Swagger",
    "SwaggerClientSecret": "1q2w3e*"
  }
}

tstwebapp scope

  • Really, we do not need to define the scope with audience settings for Frontend app. It is just for testing.
  • In keycloak console
    • click Manage realms-menu
    • click rupbes.tstrealm
    • click Client scopes-menu
    • click Create Client Scope-button
  • On the Create client scope-page
    • Protocol: OpenID Connect
    • Name: tstwebapp_scope
    • Type: Optional
    • click Save-button
  • On the tstwebapp_scope-page
    • click Mappers-tab
    • click Configure new mapper-button
    • In the Configure a new mapper-dialog
      • click Audience
  • On the Add mapper-page
    • Name: tstwebapp_scope_aud_mapper
    • Included Client Audience: tstwebapp
    • Add to access token: ON
    • Add to token introspection: ON
    • Included Custom Audience: empty
    • Add to ID token: OFF
    • Add to lightweight access token: OFF
    • click Save-button
  • Goto clients/tstwebapp-page
    • click Client scopes-tab
    • click Add client scope
    • in the Add client scopes to tstwebapp-dialog
      • choose tstwebapp_scope
      • click add/optional

tstauth scope

  • In keycloak console
    • click Manage realms-menu
    • click rupbes.tstrealm
    • click Client scopes-menu
    • click Create Client Scope-button
  • On the Create client scope-page
    • Protocol: OpenID Connect
    • Name: tstauth_scope
    • Type: Optional
    • click Save-button
  • On the tstauth_scope-page
    • click Mappers-tab
    • click Configure new mapper-button
    • In the Configure a new mapper-dialog
      • click Audience
  • On the Add mapper-page
    • Name: tstauth_scope_aud_mapper
    • Included Client Audience: tstauth
    • Add to access token: ON
    • Add to token introspection: ON
    • Included Custom Audience: empty
    • Add to ID token: OFF
    • Add to lightweight access token: OFF
    • click Save-button
  • Goto clients/tstwebapp-page
    • click Client scopes-tab
    • click Add client scope
    • in the Add client scopes to tstwebapp-dialog
      • choose tstauth_scope
      • click add/optional

tstapihost scope

  • In keycloak console
    • click Manage realms-menu
    • click rupbes.tstrealm
    • click Client scopes-menu
    • click Create Client Scope-button
  • On the Create client scope-page
    • Protocol: OpenID Connect
    • Name: tstapihost_scope
    • Type: Optional
    • click Save-button
  • On the tstapihost_scope-page
    • click Mappers-tab
    • click Configure new mapper-button
    • In the Configure a new mapper-dialog
      • click Audience
  • On the Add mapper-page
    • Name: tstapihost_scope_aud_mapper
    • Included Client Audience: tstapihost
    • Add to access token: ON
    • Add to token introspection: ON
    • Included Custom Audience: empty
    • Add to ID token: OFF
    • Add to lightweight access token: OFF
    • click Save-button
  • Goto clients/tstwebapp-page
    • click Client scopes-tab
    • click Add client scope
    • in the Add client scopes to tstwebapp-dialog
      • choose tstapihost_scope
      • click add/optional

admin role

  • In keycloak console
    • click Manage realms-menu
    • click rupbes.tstrealm
    • click Clients-menu
    • click tstwebapp-ref
  • On the tstwebapp-page
    • click Roles-tab
    • click Create Role-button
  • In the Create role-dialog
    • Role name: Admin
    • click Save-button
  • In keycloak console
    • click Manage realms-menu
    • click rupbes.tstrealm
    • click Users-menu
  • On the Users-page
    • click tstadmin-ref
  • On the tstadmin-page
    • click Role mappings-button
    • click Assign client role-button
  • In the Assign Client roles to tstadmin-dialog
    • choose Admin
    • click Assign

CustomClaimsTransformation

  • Our implementation of the CustomClaimsTransformation-class is very simple: it collects all roles of all resources. After the defining appName-var we must add additional filter.
                    foreach (var kv in jso01)
                    {
                        string appName = kv.Key;
                        ...
                    }

tenantid scope

  • In keycloak console
    • click Manage realms-menu
    • click rupbes.tstrealm
    • click Client scopes-menu
    • click Create Client Scope-button
  • On the Create client scope-page
    • Protocol: OpenID Connect
    • Name: tenantid
    • Type: Optional
    • click Save-button
  • On the tenantid-page
    • click Mappers-tab
    • click Configure new mapper-button
    • In the Configure a new mapper-dialog
      • click User Attribute
  • On the Add mapper-page
    • Name: tenantid_mapper
    • User Attribute: tenantid
    • Token Claim Name: tenantid
    • Add to access token: ON
    • Add to token introspection: ON
    • Claim JSON Type: string
    • click Save
  • Goto clients/tstwebapp-page
    • click Client scopes-tab
    • click Add client scope
    • in the Add client scopes to tstwebapp-dialog
      • choose tenantid
      • click add/optional
⚠️ **GitHub.com Fallback** ⚠️