IBM Security Verify

 View Only
Expand all | Collapse all

OAuth for External Users

  • 1.  OAuth for External Users

    Posted Fri April 24, 2020 12:42 AM
    Edited by Piyush Agrawal Fri April 24, 2020 12:51 AM
    Hello,
    I am trying to setup api-protection on our Reverse Proxy on ISAM(9.0.6). EAI is configured which creats session for internal as well as external users.
    Response Headers added by EAI java application:
    1. Common Headers:
      • am-eai-auth-level, am-eai-redir-urlam-eai-xattrs(Name, systemid,tagvalues)
    2. Internal User:
      • am-eai-user-id
    3. External User:
      • am-eai-ext-user-id, am-eai-ext-user-groups

    Demo app is enabled as explained on MMFA cookbook and junction is created with iv-creds.
    Now I am trying to consume resource like https://portal/app/mobile-demo/diag/rest.jsp with access_token received from /token endpoint.
    It works for Internal User but fails for External User and I am redirected to /eai/login for authentication. when I try https://portal/mga/sps/oauth/oauth20/userinfo for same user that it works.

    RSTR in Trace log  has response: https://drive.google.com/open?id=1Vt6Vltl-D9ik-ThaPU6ZZU6EmpjYeldE

    authorized = TRUE and

    username = EXTUSER_01

    Secure Federation - Global Settings - Point of Contact has "Non-Access Manager, Access Manager Groups and extened attributes" selected

    [oauth]
    oauth-auth = https

    default-fed-id = https://localhost/sps/oauth/oauth20

    user-identity-attribute = username

    #external-user-identity-attribute = 

    I also read 
    Allowing external users to perform OAuth authentication
    and tried external-user-identity-attribute =  am-eai-ext-user-id  but that also didn't worked  



    ------------------------------
    Piyush Agrawal
    ------------------------------


  • 2.  RE: OAuth for External Users

    Posted Fri April 24, 2020 07:11 AM
    Hi Piyush,

    When the Reverse Proxy receives an OAuth Access Token, it passes this to the AAC Runtime for validation.  It is the attributes in the token returned from this call (an STSUUser object if I remember correctly) which are being referred to in the OAuth configuration stanza.  Nothing to do with EAI HTTP headers in this case.

    By default, the AAC validation always returns the username in the "username" attribute which means WebSEAL consumes it as an internal user (as a result of user-identity-attribute = username).  In order for WebSEAL to treat the user as an external user, you must map the external-user-identity-attribute to a different attribute name and then modify the post-token mapping rule for the OAuth definition to return this attribute name (instead of username) when returning an external user.

    As a simple fix (without modifying post-token mapping rule) you can have WebSEAL treat ALL OAuth users as external users by setting:

    user-identity-attribute = dummy
    external-user-identity-attribute = username

    In this case though, internal user group membership will not be reflected in the credential.

    It's also worth noting that it is currently not possible to assert group memberships for external users during OAuth Access Token processing.

    I hope this helps you to understand the current capabilities.

    Jon.




    ------------------------------
    Jon Harry
    Consulting IT Security Specialist
    IBM
    ------------------------------



  • 3.  RE: OAuth for External Users

    Posted Fri April 24, 2020 07:18 AM
    Piyush,

    Actually - on reading the docs around OAuth support for external users  - I may be wrong to say that dynamic groups are not supported for external users.  Its seems like this is possible:
    1. Set external-group-attribute = <some attribute name> in OAuth configuration stanza
    2. Modify the post-token mapping rule to return groups using the attribute name specified

    I haven't ever tried this myself and I hadn't seen that documentation section.  I hope it works.

    Jon.

    ------------------------------
    Jon Harry
    Consulting IT Security Specialist
    IBM
    ------------------------------



  • 4.  RE: OAuth for External Users

    Posted Tue April 28, 2020 11:56 AM

    Thank you for quick help Jon, I have tested following and it works without any changes on mapping rules
    user-identity-attribute = dummy
    external-user-identity-attribute = username

    Now to support both ext and inter user I need to do map the external-user-identity-attribute to a different attribute name and then modify the post-token mapping rule for the OAuth definition to return this attribute name (instead of username) when returning an external user.
    I also need to store groups so that it is present in RSTR.

    I need to do following:
    1. Check if user is ExternalUser.

    2. Extract groups then store username and groups with ext-username and ext-groups attribute.
    3. map both attributes
    4. Modify the post-token mapping rule to return groups using the attribute name specified



    ------------------------------
    Piyush Agrawal
    ------------------------------



  • 5.  RE: OAuth for External Users

    Posted Thu May 07, 2020 04:37 PM
    Edited by Piyush Agrawal Thu May 07, 2020 06:28 PM

    Hello Jon,

    I have added following code in bottom of post token mapping rule.

    [oauth]
    external-user-identity-attribute = username
    user-identity-attribute = dummy

    if (request_type == "authorization") {
    var location_to_save = "Norway";
    OAuthMappingExtUtils.associate(state_id, "location", location_to_save);
    var registray_id = stsuu.getAttributeContainer().getAttributeValueByName("AZN_CRED_REGISTRY_ID");
    if(registray_id!=null && registray_id.indexOf("ExternalUser") !== -1){
    var ext_username = stsuu.getAttributeContainer().getAttributeValueByName("AZN_CRED_AUTHZN_ID");
    IDMappingExtUtils.traceString("Posttoken debug :: This is a External Username " + ext_username)
    stsuu.addContextAttribute(new com.tivoli.am.fim.trustserver.sts.uuser.Attribute("ext-username" ,"urn:ibm:names:ITFIM:oauth:request", ext_username));
    stsuu.addGroup(new com.tivoli.am.fim.trustserver.sts.uuser.Group("min_oversikt","urn:ibm:names:ITFIM:5.1:accessmanager",null));
    }else {
    IDMappingExtUtils.traceString("Posttoken debug :: This is a Internal User " + registray_id)
    }
    } else if (request_type == "access_token") {
    var loc = OAuthMappingExtUtils.getAssociation(state_id, "location");
    var username = stsuu.getContextAttributes().getAttributeValuesByNameAndType("username", "urn:ibm:names:ITFIM:oauth:response:attribute")
    var ext_username = stsuu.getContextAttributes().getAttributeValuesByNameAndType("ext-username", "urn:ibm:names:ITFIM:oauth:response:attribute")
    IDMappingExtUtils.traceString("Posttoken debug :: access_token :: location value from associations: " + loc);
    // IDMappingExtUtils.traceString("Posttoken debug :: access_token :: This is a External User with Registry " + registray_id)
    IDMappingExtUtils.traceString("Posttoken debug :: access_token :: This is a External Username " + ext_username)

    IDMappingExtUtils.traceString("Posttoken debug :: access_token :: This is a External Username " + username)
    stsuu.addContextAttribute(new com.tivoli.am.fim.trustserver.sts.uuser.Attribute("ext-username" ,"urn:ibm:names:ITFIM:oauth:response:attribute", "121212121212"));
    stsuu.addContextAttribute(new com.tivoli.am.fim.trustserver.sts.uuser.Attribute("LOCATION", "urn:ibm:names:ITFIM:oauth:response:attribute", loc));
    }

    I get access token response like

    {access_token=pCILqFq77uUPw18yKaxJ&LOCATION=Norway&ext-username=121212112&refresh_token=hIIkBp3sjAnvH7dLMMaefSNEkzpBoqMhDsy1&scope=read groups location email&token_type=bearer&expires_in=3599}

    However there is no change RSTR respone.
    And I do not get these custom attributes in respone from https://portal/app/mobile-demo/diag/rest.jsp with access.

    Regards,

    ------------------------------
    Piyush Agrawal
    ------------------------------



  • 6.  RE: OAuth for External Users

    Posted Fri May 08, 2020 01:49 AM
    You need (request_type == "resource") to affect what happens when an access token is presented for a resource request.

    ------------------------------
    Shane Weeden
    IBM
    ------------------------------



  • 7.  RE: OAuth for External Users

    Posted Fri May 08, 2020 05:53 AM

    Hello Shane,

    User credentials like AZN_CRED_REGISTRY_ID is available at  (request_type == "authorization")  over there I can decide if this user is External or coming from Registry with if(registray_id!=null && registray_id.indexOf("ExternalUser") !== -1)

    After decision, I want to push userId as ext-username or usrename  so that RSTR Response contains correct attribute information during request_type == "resource"

    On WebsealD conf I have following.

    [oauth]
    external-user-identity-attribute = username
    user-identity-attribute = ext-username



    ------------------------------
    Piyush Agrawal
    ------------------------------



  • 8.  RE: OAuth for External Users

    Posted Mon May 11, 2020 03:45 AM
    Hi,

    If you need some information from the credential later on in the flow, in your case a request for a resource, you have to store it in the association like you do for the "location". That way you can always retrieve the information in subsequent requests.

    ------------------------------
    Laurent LA Asselborn
    ------------------------------



  • 9.  RE: OAuth for External Users

    Posted Mon May 11, 2020 03:58 AM

    During the request_type == "authorization" flow, use the OAuthMappingExtUtils.associate() method to associate what type of user you have with the stateid of the grant. You can do this for any "attribute" of a user - as you are correct, you only have access to the user credential during /authorize.

    Later during request_type == "resource" you can use OAuthMappingExtUtils.getAssociation() to retrieve that information and set the headers that you want.



    ------------------------------
    Shane Weeden
    IBM
    ------------------------------



  • 10.  RE: OAuth for External Users

    Posted Mon May 11, 2020 03:58 PM

    Thank you very much for all helps.

    Now I have added support for both External as well as internal users and also able to pupulate groups for external users.

    Here is little code.. 
    config :

    [oauth]
    external-user-identity-attribute = username
    user-identity-attribute = ext-username
    external-group-attribute : groups

    if (request_type == "authorization") {
    var registray_id = stsuu.getAttributeContainer().getAttributeValueByName("AZN_CRED_REGISTRY_ID");
    if(registray_id!=null && registray_id.indexOf("ExternalUser") !== -1){
    var username = stsuu.getContextAttributes().getAttributeValuesByNameAndType("username", "urn:ibm:names:ITFIM:oauth:request")
    OAuthMappingExtUtils.associate(state_id, "extuser", true);
    var groups = stsuu.getAttributeContainer().getAttributeValueByName("AZN_CRED_GROUPS");
    OAuthMappingExtUtils.associate(state_id, "groups", groups);
    }
    } else if (request_type == "resource") {
    var extuser = OAuthMappingExtUtils.getAssociation(state_id, "extuser");
    var groups = OAuthMappingExtUtils.getAssociation(state_id, "groups");
    var username_response = stsuu.getContextAttributes().getAttributeValuesByNameAndType("username", "urn:ibm:names:ITFIM:oauth:response:attribute")
    if (username_response != null && username_response.length > 0 && extuser) {
    stsuu.addContextAttribute(new com.tivoli.am.fim.trustserver.sts.uuser.Attribute("ext-username" ,"urn:ibm:names:ITFIM:oauth:response:attribute", username_response[0]));
    }
    if (groups != null && extuser) {
    stsuu.addContextAttribute(new com.tivoli.am.fim.trustserver.sts.uuser.Attribute("groups" ,"urn:ibm:names:ITFIM:oauth:response:attribute", groups));
    }
    }


    ------------------------------
    Piyush Agrawal
    ------------------------------



  • 11.  RE: OAuth for External Users

    Posted Tue May 12, 2020 01:34 AM
    I'm a little concerned by this line (within the request_type == "authorization") block:

    var username = stsuu.getContextAttributes().getAttributeValuesByNameAndType("username", "urn:ibm:names:ITFIM:oauth:request")


    I'm fairly sure you should be extracting username from the Principal stsuu attributes (which represent the logged in user), rather than a parameter which might be available in ContextAttributes.

    ------------------------------
    Shane Weeden
    IBM
    ------------------------------



  • 12.  RE: OAuth for External Users

    Posted Wed May 13, 2020 06:52 AM

    Hello Shane,

    That line of code should have been deleted as variable username is not referred anywhere in req_type="authorization"
    in (request_type="resource") is have added
    var username = stsuu.getContextAttributes().getAttributeValuesByNameAndType("username", "urn:ibm:names:ITFIM:oauth:response:attribute")

    here username is coming from context attribute, oauth:response.

    I hope this is correct? or should I use username from the Principal stsuu attributes only?



    ------------------------------
    Piyush Agrawal
    ------------------------------