casapereo

how to include authenticated user's roles in JWT?


i have configured CAS as OAuth2 server. After successfull login, it returns JWT, but roles field in JWT is always empty like;

{
"sub": "dg",
...
"roles": [],
"nonce": "",
"client_id": "first-client",
"credentialType": "UsernamePasswordCredential",
...

}

how can fetch and put authenticated user's role in JWT when i login?

here is my sample service registry;

{
  "@class" : "org.apereo.cas.support.oauth.services.OAuthRegisteredService",
  "serviceId" : "http://localhost:8085/.*",
  "name" : "CAS Spring Secured App",
  "description": "This is a Spring App that usses the CAS Server for its authentication",
  "id" : 1,
  "evaluationOrder" : 1,
  "bypassApprovalPrompt": true,
  "jwtAccessToken": true,
  "clientId": "first-client",
  "clientSecret": "noonewilleverguess",
  "supportedGrantTypes": [ "java.util.HashSet", [ "authorization_code" ] ],
  "supportedResponseTypes": [ "java.util.HashSet", [ "code" ] ]
}

thanks for helps.


Solution

  • I found solution. From CAS blog (https://apereo.github.io/2017/02/22/cas51-dbauthn-tutorial/),

    Today, CAS is unable to retrieve attributes as part of authentication directly so we need to set up a separate attribute repository instance that CAS will contact once the user is fully authenticated.

    So, we need to use attribute repository (which has many types like ldap, jdbc, stub ... https://apereo.github.io/cas/development/configuration/Configuration-Properties.html#stub)

    I have configured jdbc for attribute repository. (postgresql as database)

    First of all, you need to add two dependencies to build.gradle

    compile "org.apereo.cas:cas-server-support-jdbc:${casServerVersion}"
    compile "org.apereo.cas:cas-server-support-jdbc-drivers:${casServerVersion}"
    

    then, create database where you fetch attributes. for example, named my_roles

    id (serial) | user_name (varchar(50)) | role_name (text[])
    ----------------------------------------------------------
        1       |       dg                | {'ROLE_READ', 'ROLE_WRITE'}
    

    then, configure attribute repository like this

    cas.authn.attribute-repository.jdbc[0].sql=SELECT * FROM my_roles WHERE {0}
    cas.authn.attribute-repository.jdbc[0].username=user_name
    
    cas.authn.attribute-repository.jdbc[0].user=postgres
    cas.authn.attribute-repository.jdbc[0].password=postgres
    cas.authn.attribute-repository.jdbc[0].url=jdbc:postgresql://localhost:5432/customer
    cas.authn.attribute-repository.jdbc[0].driverClass=org.postgresql.Driver
    cas.authn.attribute-repository.jdbc[0].dialect=org.hibernate.dialect.PostgreSQL95Dialect
    

    lastly, dont forget to add release policy to your service registry.

    {
      ...
      "attributeReleasePolicy" : {
        "@class" : "org.apereo.cas.services.ReturnAllowedAttributeReleasePolicy",
        "allowedAttributes" : [ "java.util.ArrayList", [ "role_name" ] ]
      }
    }
    

    so, here is the result;

    {
      "sub": "dg",
       ...
      "role_name":
      [
        "ROLE_WRITE",
        "ROLE_READ"
      ],
      "aud": "http://localhost:8085/login/oauth2/code/login-client",
      "grant_type": "AUTHORIZATION_CODE",
      ...
    }