rubyomniauth

Reading Keycloak OmniAuth::AuthHash elements with Ruby 2.7


From the Keycloak authentication token, I read the OmniAuth::AuthHash elements to extract the user's name, email and roles. Reading the name and email are quite easy based on the token retrieved through auth = request.env["omniauth.auth"] statement. Digging into the token's hierarchy provides requested information:

  user.name = auth.info.name
  user.uuid = auth.uid
  user.provider = auth.provider
  user.email = auth.info.email

I use the same method to search for user's roles list:

roles = auth.extra.raw_info.resource_access provides the following AuthHash:

#<OmniAuth::AuthHash 
    BFS.SIS=#<OmniAuth::AuthHash 
        roles=#<Hashie::Array 
            ["dataproducer", 
            "fsodataconsumer", 
            "sisdatasteward"]
            >
        > 
    BFS.SIS.DAL=#<OmniAuth::AuthHash 
        roles=#<Hashie::Array 
            ["kd_getLoadReports", 
            "kd_createTables", 
            "kd_readTables", 
            "kd_deleteTables"]
            >
        > 
    BFS.SIS.DPS.KEYSTORE=#<OmniAuth::AuthHash 
        roles=#<Hashie::Array 
            ["keymanagement_key_read", 
            "keymanagement_keystore_read"]
            >
        > 
    BFS.SIS.SMS=#<OmniAuth::AuthHash 
        roles=#<Hashie::Array 
            ["kdDatasetInformation_read", 
            "codeLists_update", 
            "definedVariables_set_status_validation_in_progress", 
            "hierarchicalCodeLists_update", 
            "hierarchicalCodeLists_create", 
            "kdDatasetInformation_delete", 
            "kdDatasetInformation_update", 
            "kdDataStructureDefinitions_create", 
            "kdDataStructureDefinitions_update", 
            "kdDataStructureDefinitions_delete", 
            "kdDataStructureDefinitions_read",
            "kdDatasetInformation_create", 
            "definedVariables_set_status_open_from_rejected"]
            >
        > 
    BFS.SIS.UI=#<OmniAuth::AuthHash 
        roles=#<Hashie::Array 
        ["bfs.sis.portal"]
        >
    >
>

There is the issue: as key names contain a '.', I cannot continue accessing subkeys with the syntax key.subkey to retrieve the array of roles for the BFS.SIS and BFS.SIS.SMS keys.

How could I extract the arrays from these keys?

Thanks for your help!


Solution

  • Well, I can't dig into the hash key.subkey syntax, but I can enumerate the subkeys. And then I can check if some match with needed entries, and extract child roles.

    Here is the solution I implemented:

      auth = request.env["omniauth.auth"]
      roles = Array.new
      activities = auth.extra.raw_info.allowlists.statisticalActivities
      resources_accesses = auth.extra.raw_info.resource_access
      resources_accesses.each do |access|
        puts access # Provides the resources_access hash
        puts access[0] # Provides the resources_access label
        puts access[1] # Provides the resources_access roles array
        # Check if label matches needed entries
        if ["BFS.SIS.SMS", "BFS.SIS", "BFS.SIS.SCHEDULER"].include? access[0].to_s
          access[1].roles.each do |role|
            # Store each role in the roles array
            roles << role
          end
        end
      end
    

    This list of roles for a user will help building the list of abilities for CanCanCan gem.