Uploaded image for project: 'OpenAM'
  1. OpenAM
  2. OPENAM-9074

wrong acr_values mapping makes the authorization flow looping

    Details

    • Support Ticket IDs:

      Description

      How to reproduce

      • Create a oauth2 environment (provider and client)
      • Create a loa mapping
      "loaMapping": {
          "chain1": "ldapService"
        },
      

      Note: as OPENAM-9025 is not fixed yet, you can use

      curl -X PUT -H "Accept: application/x-www-form-urlencoded" -H "Content-Type: application/json" -H "iplanetDirectoryPro: AQIC5wM2LY4SfczKl0s4FXIuX3VKU5CiIFBTxZZI3oR2Pdw.*AAJTSQACMDEAAlNLABQtNzkzMDc5MTgwNDAwNDgyMjc2OQACUzEAAA..*" -H "Cache-Control: no-cache" -H "Postman-Token: 0dc1f260-0ca9-8181-d2cc-dd657b55964e" -d '{
         "storeOpsTokens":true,
         "alwaysAddClaimsToToken":false,
         "oidcClaimsScript":"36863ffb-40ec-48b9-94b1-9a99f71cc3b5",
         "keypairName":"test",
         "supportedScopes":[
            "openid|",
            "email|Your email address",
            "address|Your postal address",
            "phone|Your telephone number(s)",
            "profile|Your personal information"
         ],
         "responseTypeClasses":[
            "id_token|org.forgerock.openidconnect.IdTokenResponseTypeHandler",
            "code|org.forgerock.oauth2.core.AuthorizationCodeResponseTypeHandler",
            "token|org.forgerock.oauth2.core.TokenResponseTypeHandler"
         ],
         "issueRefreshTokenOnRefreshedToken":false,
         "supportedSubjectTypes":[
            "public"
         ],
         "defaultACR":"",
         "jkwsURI":"",
         "jwtTokenLifetime":3600,
         "scopeImplementationClass":"org.forgerock.openam.oauth2.OpenAMScopeValidator",
         "supportedIDTokenSigningAlgorithms":[
            "ES384",
            "HS256",
            "HS512",
            "ES256",
            "RS256",
            "HS384",
            "ES512"
         ],
         "deviceCodeLifetime":300,
         "devicePollInterval":5,
         "displayNameAttribute":"cn",
         "defaultScopes":[
            "address",
            "phone",
            "openid",
            "profile",
            "email"
         ],
         "supportedIDTokenEncryptionAlgorithms":[
            "RSA1_5"
         ],
         "accessTokenLifetime":3600,
         "customLoginUrlTemplate":"",
         "hashSalt":"",
         "savedConsentAttribute":"",
         "authenticationAttributes":[
            "uid"
         ],
         "tokenSigningECDSAKeyAlias":[
            "ES512|test",
            "ES256|test",
            "ES384|test"
         ],
         "modifiedTimestampAttribute":"",
         "codeLifetime":120,
         "tokenSigningAlgorithm":"HS256",
         "issueRefreshToken":false,
         "supportedIDTokenEncryptionMethods":[
            "A128CBC-HS256",
            "A256CBC-HS512"
         ],
         "generateRegistrationAccessTokens":true,
         "codeVerifierEnforced":false,
         "completionUrl":"",
         "supportedClaims":[
            "phone_number|Phone number",
            "family_name|Family name",
            "given_name|Given name",
            "locale|Locale",
            "email|Email address",
            "profile|Your personal information",
            "zoneinfo|Time zone",
            "address|Postal address",
            "name|Full name"
         ],
         "loaMapping":{
            "chain1":"ldapService"
         },
         "verificationUrl":"",
         "claimsParameterSupported":false,
         "allowDynamicRegistration":false,
         "tokenSigningHmacSharedSecret":"cx/2OTDM4Gx63O9vxxnhSme9BMUzIZU2CP9/Figm5cI=",
         "refreshTokenLifetime":604800,
         "createdTimestampAttribute":"",
         "clientsCanSkipConsent":false,
         "statelessTokensEnabled":false,
         "idTokenInfoClientAuthenticationEnabled":true,
         "_id":"",
         "_type":{
            "_id":"oauth-oidc",
            "name":"OAuth2 Provider",
            "collection":false
         }
      }' "http://openam.example.com:13081/openam/json/realm-config/services/oauth-oidc"
      

      Then try the authorization grant flow 'acr_values=wrong_chain'

      http://openam.example.com:13081/openam/oauth2/authorize?response_type=code&client_id=myClientID&realm=%2F&scope=openid%20profile&redirect_uri=http%3A%2F%2Fopenam.example.com%3A13081%2Fopenid%2Fcb-basic.html&state=af0ifjsldkj&acr_values=wrong_chain

      expected result

      A error message telling you that this acr_values doesn't map the arm_mapping

      Current result

      We currently check if the acr_values is valid with the token authentication contexte. It doesn't so we redirect the user to the login page. => OK

      We build the URL like this

       private URI buildDefaultLoginUrl(OAuth2Request request, String gotoUrl, String acrValues, String realm,
                  String moduleName, String serviceName, String locale) throws URISyntaxException, ServerException,
                  NotFoundException {
      
              final Request req = request.getRequest();
              final String authURL = getAuthURL(getHttpServletRequest(req));
              final URI authURI = new URI(authURL);
              final Reference loginRef = new Reference(authURI);
      
              if (!isEmpty(realm)) {
                  loginRef.addQueryParameter(OAuth2Constants.Custom.REALM, realm);
              }
              if (!isEmpty(locale)) {
                  loginRef.addQueryParameter(LOCALE, locale);
              }
      
              // Prefer standard acr_values, then module, then service
              if (!isEmpty(acrValues)) {
                  final ACRValue chosen = chooseBestAcrValue(request, acrValues.split("\\s+"));
                  if (chosen != null) {
                      loginRef.addQueryParameter(chosen.method.getIndexType().toString(), chosen.method.getName());
      
                      // Adjust the GOTO url to indicate which acr value was actually chosen
                      req.getResourceRef().addQueryParameter(OAuth2Constants.JWTTokenParams.ACR, chosen.acr);
                  }
              } else if (!isEmpty(moduleName)) {
                  loginRef.addQueryParameter(MODULE, moduleName);
              } else if (!isEmpty(serviceName)) {
                  loginRef.addQueryParameter(SERVICE, serviceName);
              }
      
              loginRef.addQueryParameter(GOTO, gotoUrl);
      
              return loginRef.toUri();
          }
      

      This is where is is interesting:

       final ACRValue chosen = chooseBestAcrValue(request, acrValues.split("\\s+"));
                  if (chosen != null) {
      

      If the ACRValue match with none of the loaMapping, we ignore the acr_value.

      Possibility of fix

      Solution 1 : we considere that every acr_values should correspond to a chain thanks to the loaMapping

      That the solution I prefere, as in my opinion, I considere the request invalid if one of the acr_values isn't mapping a chain.

      Solution 2: If a acr_value is wrong, so not mapping found, we ignore this value.

      Therefore, we should clean the list of acr_values first before doing

          private void setCurrentAcr(SSOToken token, OAuth2Request request, String acrValuesStr)
                  throws NotFoundException, ServerException, SSOException, AccessDeniedException,
                  UnsupportedEncodingException, URISyntaxException, ResourceOwnerAuthenticationRequired {
      

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                dipu.seminlal Dipu Seminlal
                Reporter:
                quentin.castel Quentin CASTEL [X] (Inactive)
              • Votes:
                0 Vote for this issue
                Watchers:
                5 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: