39 Configuring OAuth Services in 12c

Oracle Access Management (OAM) OAuth helps secure access to services. OAuth services are enabled as a part of the OAM 12c installation process. OAM provides an API based approach for configuring OAuth Services. During set up, you need to configure OAuth clients and resources in Oracle Access Manager.

This chapter contains the following sections:

39.1 Set-up OAuth Services

You are an administrator and are responsible for setting up OAuth. You want to configure OAuth to secure access to services. During set up, you need to configure OAuth clients and resources in Oracle Access Manager. This section describes how to enable and manage OAuth Services using APIs.

You have the following responsibilities as an administrator.

  • Configure and manage OAuth Identity Domain

  • Configure and manage OAuth Resources

  • Configure and manage OAuth Clients

  • Ensure that the communication between different services is secure

  • Access protected services through REST API calls

Pre-requisite for OAuth configuration

Setting Up OAuth: Task Flow

This section describes the high-level tasks in setting up OAuth in OAM. You start setting up OAuth by creating an identity domain and registering a resource. An OAuth Resource needs to be registered before registering an OAuth Client, as the resource information, specifically the API details, are required while registering a client.

  1. To create an identity domain using REST API calls, refer to Creating an Identity Domain

  2. To register a new resource using REST API calls, refer to Creating a Resource

  3. After a resource is registered, you can configure and register an OAuth Client. To register a trusted client using REST API calls, refer to Creating a Client

For more information on OAuth REST APIs, See REST API for OAuth in Oracle Access Manager

39.2 Configuring OAuth Services Settings

OAuth Services has many components that must be configured before the authorization protocol can be used.

Descriptions of the OAuth Services components and how they work together can be found in Understanding the OAuth Services Components. This section includes information on configuring the OAuth Services components.

This section describes the following topics:

39.2.1 Creating an Identity Domain

An Identity Domain corresponds to the notion of a tenant. All clients and resource servers are created under an Identity Domain.

The important parameters used in the curl command to create an identity domain are:
  • identityProvider: UserIdentityStore to perform the authentication against (Password Grant Flows). If not specified this is defaulted to the DefaultIdentityStore - "UserIdentityStore1"

  • errorPageURL: Custom error page to be used in the case of 3 legged flows. If not specified it is defaulted to OAM server's error page.

  • consentPageURL: Customer consent page to be used in case of 3 legged flows. If not specified uses the custom consent page shipped with OAM.

  • tokenSettings: Token defaults are maintained at the IdentityDomain level. If tokenSettings is not specified the default values for the ACCESS_TOKEN and others are used.

    Note:

    If RefreshToken needs to be generated along with AccessToken, refreshTokenEnabled=true must be set, under ACCESS_TOKEN settings.

Endpoint for CRUD operations:

http:<AdminServerHost:Port>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/oauthidentitydomain

Note:

Use Content-Type:application/json in the REST API HTTP request. 

There are 2 ways to create the Identity Domain

  • Simple: In this mode, just the name and description of the IdentityDomain to be created are used. The rest of the values are defaulted.

  • Detailed: In this mode, you can give specific values to the different parameters.

  1. In Simple mode, a sample curl command to create a domain is shown.
    curl -i -H 'Content-Type: application/x-www-form-urlencoded' -H 'Authorization:Basic dXNlcm5hbWU6cGFzc3dvcmQ=' 
    --request POST http:<Servername>:<Port>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/oauthidentitydomain -d 
    '{"name":"TestDomain","description":"Test Domain"}'
    
    
  2. In Detailed mode, a sample curl command to create a domain using scopes is shown below.
    curl -i -H 'Content-Type: application/x-www-form-urlencoded' -H 'Authorization:Basic dXNlcm5hbWU6cGFzc3dvcmQ=' --request 
    POST http:<Servername>:<Port>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/oauthidentitydomain -d 
    '{"name":"TestDomain","identityProvider":"UserIdentityStore1","description":"Test Domain"}'
    
    HTTP/1.1 200 OK
    Date: Fri, 28 Jul 2017 13:01:41 GMT
    Content-Length: 860
    Content-Type: text/plain
    X-ORACLE-DMS-ECID: 78d30c19-07b6-4ac2-a39b-f1cbd8182ebb-000003fd
    X-ORACLE-DMS-RID: 0
    Set-Cookie: JSESSIONID=_oGJSc7Vt2vIWLNQ_uwYCZz151JqOXewJRIkyvstnnio8WsNborT!-1875566563; path=/; HttpOnly
    
    Sucessfully created entity - OAuthIdentityDomain, detail - OAuth Identity Domain :: Name - TestDomain, 
    Id - 1636d0492f36447087780abdfdc4c15f, Description - Test Domain, TrustStore Identifiers - [TestDomain], 
    Identity Provider - UserIdentityStore1, TokenSettings - [{"tokenType":"ACCESS_TOKEN","tokenExpiry":3600,"lifeCycleEnabled":false,"refreshTokenEnabled":false, "refreshTokenExpiry":86400,"refreshTokenLifeCycleEnabled":false}, 
    {"tokenType":"AUTHZ_CODE","tokenExpiry":3600,"lifeCycleEnabled":false,"refreshTokenEnabled":false,"refreshTokenExpiry":86400,
    "refreshTokenLifeCycleEnabled":false}, {"tokenType":"SSO_LINK_TOKEN","tokenExpiry":3600,"lifeCycleEnabled":false,
    "refreshTokenEnabled":false,"refreshTokenExpiry":86400,"refreshTokenLifeCycleEnabled":false}], 
    ConsentPageURL - /oam/pages/consent.jsp, ErrorPageURL - /oam/pages/error.jsp, CustomAttrs - null
  3. In Detailed mode, a sample curl command to configure expiry time of ID_TOKEN is shown below.
    curl --location --request PUT 'http://<AdminServerHost>:<AdminServerPort>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/oauthidentitydomain?name=DemoDomain'
    --header 'Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ='
    --header 'Content-Type: application/json'
    --data '{ "tokenSettings": [ { "tokenType": "ID_TOKEN", "tokenExpiry": 600 } ] }'
    
    
    Sucessfully modified entity - OAuthIdentityDomain, detail - OAuth Identity Domain :: Name - DemoDomain,
     Id - 0a17cf470ffa4006b4acfef2cb685202, Description - Demo Domain, TrustStore Identifiers - [DemoDomain],
     Identity Provider - UserIdentityStore1, TokenSettings - [{"tokenType":"ACCESS_TOKEN","tokenExpiry":3600,"lifeCycleEnabled":true,"refreshTokenEnabled":true,"refreshTokenExpiry":99999,"refreshTokenLifeCycleEnabled":true},
     {"tokenType":"AUTHZ_CODE","tokenExpiry":3600,"lifeCycleEnabled":true,"refreshTokenEnabled":true,"refreshTokenExpiry":99999,
    "refreshTokenLifeCycleEnabled":true}, {"tokenType":"SSO_LINK_TOKEN","tokenExpiry":3600,"lifeCycleEnabled":true,
    "refreshTokenEnabled":true,"refreshTokenExpiry":99999,"refreshTokenLifeCycleEnabled":true}, {"tokenType":"ID_TOKEN","tokenExpiry":600,"lifeCycleEnabled":false,"refreshTokenEnabled":false,"refreshTokenExpiry":0,"refreshTokenLifeCycleEnabled":false}],
     ConsentPageURL - /oam/pages/consent.jsp, ErrorPageURL - /oam/pages/error.jsp, CustomAttrs - {"isDcrRegEnabled":"false","consentExpiryTimeInMinutes":"182"}, issueTLSClientCertificateBoundAccessTokens - false, keyPairRolloverDurationInHours - 48

    Note:

    When rolling back to earlier patches, domain APIs throws 422 Unprocessable Entity (WebDAV) (RFC 4918) as ID_TOKEN settings were not available. A workaround for this is to delete ID_TOKEN settings from the updated domains. In order to address this, we have added a forceUpdate argument to PUT requests, which overrides the current token settings with the ones requested
    Sample Request
    curl --location --request PUT 'http://<AdminServerHost>:<AdminServerPort>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/oauthidentitydomain?name=iddomain&forceUpdate=true' \
    --data '{
        "tokenSettings": [
            {
                "tokenType": "ACCESS_TOKEN",
                "tokenExpiry": 3600,
                "lifeCycleEnabled": true,
                "refreshTokenEnabled": true,
                "refreshTokenExpiry": 99999,
                "refreshTokenLifeCycleEnabled": true
            },
            {
                "tokenType": "AUTHZ_CODE",
                "tokenExpiry": 3600,
                "lifeCycleEnabled": true,
                "refreshTokenEnabled": true,
                "refreshTokenExpiry": 99999,
                "refreshTokenLifeCycleEnabled": true
            },
            {
                "tokenType": "SSO_LINK_TOKEN",
                "tokenExpiry": 3600,
                "lifeCycleEnabled": true,
                "refreshTokenEnabled": true,
                "refreshTokenExpiry": 99999,
                "refreshTokenLifeCycleEnabled": true
            }
        ]
    }'

Table 39-1 OAuth Identity Domain Details

Property Description Values
tokenType Refers to the token types from the defined domain. ACCESS_TOKEN, AUTHZ_CODE, SSO_LINK_TOKEN, ID_TOKEN
tokenExpiry The default value defined for every token type. 3600

Note:

This is the default value.
lifeCycleEnabled The default value is false. It is set to true for every token type. false
refreshTokenEnabled The default value is false. It is set to true for every token type. false
refreshTokenExpiry Specifies the refresh token expiry period for any token type. 86400

Note:

This is the default value.
refreshTokenLifeCycleEnabled The default value is false. It is set to true for every token type. false
ConsentPageURL Refers to the custom JSP page for consent. /oam/pages/consent.jsp

Note:

This is the default value.
ErrorPageURL Refers to the custom JSP page for error. /oam/pages/error.jsp

Note:

This is the default value.
CustomAttrs Refers to custom defined attributes for Identity Domain. null

Note:

This is the default value.
oldSecretRetentionTimeInDays Refers to configurable time in days for which the old client secret will continue to work. The default value is 0, indicating that the old secret will not be accepted. The maximum limit is 365 days.

Note:

  • This custom attribute can be defined both at the domain-level and at the client-level. However, the value defined at the client-level takes precedence.
  • It is recommended to update your client’s secret every six months.
39.2.1.1 Token Signing Using Third-Party Certificates

Access tokens can be signed using a self-signed key pair generated out-of-the-box. OAM extends this support to allow signing of access tokens using third-party key pairs. Administrators can manage the life-cycle of the key pair using REST APIs.

OAM Bundle Patch 12.2.1.4.210920 and Later Releases. This content applies only to OAM Bundle Patch 12.2.1.4.210920 and later releases.

To allow signing of access tokens using third-party certificates, perform the following steps:

  1. Upload the required key pair to the server and create an alias for that key pair using the https://<admin-host>:<admin-port>/oam/services/rest/ssa/api/v1/keypairadmin/keypair REST API.
    For example, you can upload the public and private key to the server and create an alias for that key pair called KeyPair1 as shown:
    curl --location --request POST 'https://<admin-host>:<admin-port>/oam/services/rest/ssa/api/v1/keypairadmin/keypair' \
    --header 'Content-Type: application/json' \
    --header 'Authorization: Basic dGVzdDp0ZXN0=' \
    --data-raw '[
        {
            "aliasName":"KeyPair1",
            "publicKey":"MIIERDCCAyygAwIBAgIJAJ2KzwSAbV8GMA0GCSqGSIb3DQEBBQUAMIGjMQswCQYDVQQGEwJERTEQMA4GA1UECBMHQmF2YXJpYTEPMA0GA1UEBxMGTXVuaWNoMRgwFgYDVQQKEw9NSVQteHBlcnRzIEdtYkgxFjAUBgNVBAsTDUhCQlRWLURFTU8tQ0ExGzAZBgNVBAMTEml0di5taXQteHBlcnRzLmNvbTEiMCAGCSqGSIb3DQEJARYTaW5mb0BtaXQteHBlcnRzLmNvbTAeFw0xNzEwMjIxMTA4NDJaFw0yMjEwMjExMTA4NDJaMIGhMQswCQYDVQQGEwJERTEQMA4GA1UECAwHQmF2YXJpYTEPMA0GA1UEBwwGTXVuaWNoMRgwFgYDVQQKDA9NSVQteHBlcnRzIEdtYkgxEDAOBgNVBAsMB1RFU1QgQ0ExHzAdBgNVBAMMFnRlc3Rib3gubWl0LXhwZXJ0cy5jb20xIjAgBgkqhkiG9w0BCQEWE2luZm9AbWl0LXhwZXJ0cy5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4GnIWd1Mxts1ZDCt6JPTV0mvFn+ZrwqE/4WFNAaqtRaChaP21NQ1H55NFNYo1Dl2AhDDNK1MUk+rq6LZOWm8XiuMBA/fs3uBNEloa9WYoAEb3ozS14AG+d1yq41diNl4F2ys1f10s4gW/H27UHl2G1Bgb9Zx1yFZHYItjGKpTl5I8fO/MQtWFvqoK9rY0UxYHpS6Tnfc7ArrQMNsOFu4015N8JuDDtizNxsq8sOK2MgQZNeuOg+ST+8jrJR8CbxRuvejfhZM2QMfBeACjFyxQGBn4UZkys46Y5lXJCx7n6Zix1p+y9qNrJjEdup9O9q9VIjS86K1wPz62JqaVl6R7AgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBRCN+ztRIOc3iF130yCGbkBAOK+oTAfBgNVHSMEGDAWgBTEbk/zoRG4/M/5q7Z9Er8rKAgPcjANBgkqhkiG9w0BAQUFAAOCAQEAUHAPBfoLvB/krCTgBZhswxbLutQCB8hDG3rPspJsD3TUHhSUlWxHulxSBMfNKMv1lKA1SX/4+2epkpz825eO47u0SLsmSlXdzfsOt0GLqbB9IQOnTxu2/3z/gtNaHUlDo2JQf24CfGAFQVv+2Fp8+3B5DvKvuHIEGR6A27Ua/wBR78Of1jdwvMBEgDeN5+R5r0HjCt/A5ODdG9j8p+wpYQaMWZ6A2iOMWEdgvQnQeW2B5gD9mOV1gCh4HCYMXf/apuWZEoafm6qd1Q+SeB4D/LbsnDQN1uzqrTj8Jg7C1h55KNMeYECYWBKiqeztxBdLGEjkqCZarnUNYEfzXDPbpw==",
            "privateKey":"MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIjJCdZa17o0YCAggAMBQGCCqGSIb3DQMHBAhwwPasgNmZVASCBMjTi8XLv8f7Os7vuJE8n4WmQCSp7Q6LwZO5cdvBtvQDbKzTlZbRudIz54jDLQDkaXT8zPBIPdnF4frjKqIzrK1EY0+3oTILGeWabxvbvSDkdbyES98euhunNZcBnvm+JYmAm6IcMv11kPu57as8uUUDMoFpqsy7DZ7QhE9BxKdKSAkyPXkefuB5UpYnTjzZgES9BAYNedhjpKDXX2et1PwnFpbTndbT6Ur5SbnzMpZYPuG+G9+sedCJMpspd8yS178hf0UfftAhKLHpIjzQGYWh+c3BvMzd3f7xIK1/iTme5TJV3SOQNPEQ7E1tyVtwip/LvXEKEUvw0yOsFBqS+teHMT9wLnCn5oAXyuFI7RcH0x3Y57AJu4xthoL71wSoiYB+WrZD5AmQmMfAliO1AC4LA8TLGID0GVwM58AD8p+9QJwABi4rag0wwuBDOBt3FOqc0donyo4/NS2S8WZmr93A7WwB9KzD1SrYviPpIqPNSsExosT7dgcW0LzmKcE1zqzkPb1C2nzQu+Y8vmlNyDUW3jp0Ao0fudJZJ1+BEiNc1wMnBQXNkE42u7rDF8/Jo2r8tsOKa0ErHoRjNLpyzsfjLp+C6wwBcnCJRxSXwvf+CPeN09cMkR3Jt2qzwZJ22NvzeTgK+2vA0dCH4rFgylHKvag2FhGYw5O/8JWMN5mKLUB03GmMz3PjRG7DT5acEnO1YV3AAoeoSD84RNRS8oxH7AOhSwvMi8Xu/SqkuYfRy2hr8oXEmE5M790aPiGkDUTY1A0pPYr02fvQFf5P3VQ1kDT3+W402dDl7yVGmvgWSz+ABm8cGS1eyTq/O43XEPD55LH6o8gnFH3Ba6/sI6vRTDkn0mqVuxTJgpnpMpYsitcLNl066OFgzzdvBdxREp5qjy+meqdX+j6rm42CTnDDuWsyyKvFzK89LD4o0QjHdt+t9sMhS5PYcj5QTAqKFoWVlAFru41th7nSnRUzonBKaD40qsgnUHOWdRSnMRqmoXbTMKt6mx6xgPPeK266GSqMcrXCfdzRwU3Ad1Xw6fAcFXnqbI9CQuQ8ADSg6lW3BZqZyM0I+jr9vib1tdTrTuMkDtDg1gDcVzcgaRLJ7GJF2Az5mfyGs61uDBhycxRgAhOA7ehu7cEU708y5UYjaTizWtGmpnAt+bS7KNopqEhzP6OpP8FMKfvqvgwMWpm++AyEMbAswhjaz9LjI0HtTuQTKlBLBHzm1TVIOwn+5bd4W917uVfXCJdS8OaEwkFzGBXhJvkwBGlMvYO+gr3Kbio2O2QfjfXNlgob8EfDMPH3N8gkpdSulLzYEzK+2lNz3h1bm07evz2w2xTy9PYP1UD1UCugFA18RI+4YdnaIBSyeReODRhaE4AF+T2oAu3rE9c9iCauC9QOSICsULyGbLny54R9tk1wdAJI4xASPHoizz8GqqF8s6Y2/F46LS+43042rkfQmvdr5yrjYsF7YphSQzp7MREq+QwgXjC8kc5LMn81o2Ii6DcsyEQVBimfu055FFE1IHnUYKKBrxJU77+jpqb/pXlqvsm7ucBVCpRDl1EvRkSji8qPk60aFotPfNNxOvIWLOjHkaYzfASbtZ/G8H2nZMZWTdtxY+tgS8R6Bo+sJZH/NnE="
        },
        {
            "aliasName":"KeyPair2",
            "publicKey":"MIIEqDCCApCgAwIBAgIUK5Ns4y2CzosB/ZoFlaxjZqoBTIIwDQYJKoZIhvcNAQELBQAwfjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDzANBgNVBAoMBkJhZFNTTDExMC8GA1UEAwwoQmFkU1NMIENsaWVudCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xOTExMjcwMDE5NTdaFw0yMTExMjYwMDE5NTdaMG8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ8wDQYDVQQKDAZCYWRTU0wxIjAgBgNVBAMMGUJhZFNTTCBDbGllbnQgQ2VydGlmaWNhdGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHN18R6x5Oz+u6SOXLoxIscz5GHR6cDcCLgyPax2XfXHdJs+h6fTy61WGM+aXEhR2SIwbj5997s34m0MsbvkJrFmn0LHK1fuTLCihEEmxGdCGZA9xrwxFYAkEjP7D8v7cAWRMipYF/JP7VU7xNUo+QSkZ0sOi9k6bNkABKL3+yP6PqAzsBoKIN5lN/YRLrppsDmk6nrRDo4R3CD+8JQl9quEoOmL22Pc/qpOjL1jgOIFSE5y3gwbzDlfCYoAL5V+by1vu0yJShTTK8oo5wvphcFfEHaQ9w5jFg2htdq99UER3BKuNDuL+zejqGQZCWb0Xsk8S5WBuX8l3Brrg5giqNAgMBAAGjLTArMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgeAMAsGA1UdDwQEAwIF4DANBgkqhkiG9w0BAQsFAAOCAgEAZBauLzFSOijkDadcippr9C6laHebb0oRS54xAV70E9k5GxfR/E2EMuQ8X+miRUMXxKquffcDsSxzo2ac0flw94hDx3B6vJIYvsQx9Lzo95Im0DdTDkHFXhTlv2kjQwFVnEsWYwyGpHMTjanvNkO7sBP9p1bN1qTE3QAeyMZNKWJk5xPlU298ERar6tl3Z2Cl8mO6yLhrq4ba6iPGw08SENxzuAJW+n8r0rq7EU+bMg5spgT1CxExzG8Bb0f98ZXMklpYFogkcuH4OUOFyRodotrotm3iRbuvZNk0Zz7N5n1oLTPlbGPMwBcqaGXvK62NlaRkwjnbkPM4MYvREM0bbAgZD2GHyANBTso8bdWvhLvmoSjsFSqJUJp17AZ0x/ELWZd69v2zKW9UdPmw0evyVR19elh/7dmtF6wbewc4N4jxQnTqIItuhIWKWB9edgJz65uZ9ubQWjXoa+9CuWcV/1KxuKCbLHdZXiboLrKm4S1WmMYWd0sJm95H9mJzcLyhLF7iX2kK6K9ug1y02YCVXBC9WGZc2x6GMS7lDkXSkJFy3EWhCmfxkmFGwOgwKt3Jd1pF9ftcSEMhu4WcMgxi9vZr9OdkJLxmk033sVKI/hnkPaHwg0Y2YBH5v0xmi8sYU7weOcwynkjZARpUltBUQ0pWCF5uJsEB8uE8PPDD3c4=",
            "privateKey":"MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIFGJVk+2yRcECAggAMBQGCCqGSIb3DQMHBAgI8pa9pbh96ASCBMgOltVUbtkUcupvbL2Eh2Cy5YIO9cCQcgfA9xTBUnhCivgyPDaqJ6iM0ryIdVdvHLn0gySpqo3TSUZheygU7cBQvILdTt6Of02yf3Gp7Xs8CAs3qNODUTK51QGwDSJ4zyFquiEUNgSeG6UMji/9Y09791ONVYmvz7ZqPwYOK0HwSOF9ttXzAVA9GKMpnCy97G0ezkzFhInBtf/nMYuRbWwCddN/zt0IX7Yo6AnF91QzluGUXGnENJufvKj7q3DSTVolWyQgHlCrq/0BMextYxe9GSjHF2UTCUDbmi6Vv1Z3ezkkKuQMPXCZ/qOgQFyx4PWmtXKBj3EPZYTI0dTebhCmXv614UIglFwyPQPLVJR0GlZIRAw4pM01BBMSlwLrjMBcW7EUUJ7DyvBX9bJe7vZ0nMS1kSQyWU031RRbK1Yt16QtdV+sw9ZCCB8ZEQ+4y06dJvpapmGzH5QjSZzgh9Sp+wXoqiovvjdKcxzPg3WjclSj/MtetDlBDDq9K1hEuc5eNL8Qr/yiX8C/9Uk8JbcUaJMeq4H2nZiOgY+DzpMuEEJJo81WztrrFu8KB2oeky5EZ3akB0OKy0bL8MScLkVNbJFzv290P/Jj/y6JTo2VzoF+bu5l9mySjDMxci218+NC7oOwiIzNJPR3IWoLmoRYoXUAyl1tTaZWAmHai6iypXSeskc1Ezvp4STMK7oqbkf2DXNY+F5wDP3HdD1Yb6FrziKbrQ67+qY+XSXIV/Abm2c5ELnHsIFkGV/xDdWkoh+C5Lg8XssnqH0tcuCuyGqZKDHBVoa/xvpq5rCd2i2MWrImC0lvyOksDfsrluzAXSXPmtHwiPir6iDb5srlmaJCEKvrRdNxNK28kFzCshNtEivEiu9DH+5cMdbAilBYEFbk0N/uRNzG4doieCElYMD/yZE51oq7S7JVq61Ff7O6KT1SZQVusumCeyE28HlocyWuNMMc9jJ1YJ68dBH/9YPeGNeBu8qCgXdFgSBEdcAD2p5FNzMyZuWRwENne7MNt8EgUBLpc+kPZ07lRNyF8GFx3A+U2etNPjGA6a64jGhcM5KcZreJ8wffprFpAuY4rFPJkQ5xyyaxlRrrlhSOrAj6wTiNZVWcuA20URdilhOpHzbq+J9zrtnNCLMkIVCB8YFtjt5puciltD3cD8eg5DPhQntLVdJiUfyZsApC8RWamwfzCsN9MRo70Qxl4pC4qKYmBDYdyGeQpfi7C69+7153AKqr2ZjhCdaJ3/g1EAh3PJOCKqetrPqkNfZnEMJz+9nhmgcIn10l3tlDFbB1Biship6GHx+d6PT7AZRei704JsAnyCOD1xyWd8UlWlXgbr0zQol4c5KiByho7mZlajVWzqKapz4OBnTFKmWW9KoFSXWp0kKGcxAGPC+FL8EGXErvSlmbVf8MKfs4eLnKidzL1MKW1pS4n9cwKHmZjPVv0YYUgGEw8FAuH0DjQBvnLrCbWLY3DXHR/GAf9hagSa0G0FO7MvQcSWE5eqXwICJ9PMhxiEEx9PF0QJuMxhs6bni/thZqFOYDN0kbmSNntB0kG4EwWCxKoegEUMX7Ug5R0IGilLJ37Q9NQvh21msH3mi8KcfuO1keeSdZJPbFFkCVHCPMGx6QRY8="
        }
    ]'
    You can also upload the key pair using the p12 file and create an alias KeyPair1 for that key pair as shown in the following example:

    Note:

    The key size must be at least 2048 bits and the p12 file must contain only one public-private key pair.
    curl --location --request POST 'https://<admin-host>:<admin-port>/oam/services/rest/ssa/api/v1/keypairadmin/keypair?password=<your_password>&aliasName=KeyPair1' \
    --header 'Content-Type: application/x-pkcs12' \
    --data-binary '@/u01/keypairfiles/p12files/your_file-client.p12'
    , where password is the password of the p12 file.

    For more information, see Add a New KeyPair REST API documentation.

  2. Associate the key pair with the required OAuth Identity Domain using defaultSigningKeyPair and keyPairRolloverDurationInHours.

    For example,

    curl --location -g --request PUT 'https://<admin-host>:<admin-port>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/oauthidentitydomain?name=Domain1' \
    --header 'Authorization: Basic dGVzdDp0ZXN0=' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "defaultSigningKeyPair": "KeyPair1",
        "keyPairRolloverDurationInHours": "24"
    }'

    For more information, see Identity Domain REST Endpoints documentation.

Note:

To perform signature verification of the tokens, the trust certificate can be retrieved using the following jwks_uri: http://<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/security.

The jwks_uri can be retrieved using OpenIDConnect Discovery Endpoint. For details, see Configuring OpenIDConnect Discovery Endpoint

39.2.2 Enabling Consent Management

You can enable Consent Management for each of the OAuth Identity Domains or all the OAuth Identity Domains in OAM.

During the 3-legged OAuth flow, OAM presents a consent page enabling you to grant access to the resource. If Consent Management is enabled, your consent is saved, and OAM skips the consent on subsequent 3-legged OAuth flows. For details about the 3-legged OAuth Flow, see Understanding 3-Legged Authorization

By default, Consent Management is disabled.

To enable Consent Management per OAuth Identity Domain, create or modify the OAuth Identity Domain by setting the custom attribute consentExpiryTimeInMinutes using the Admin Server OAuth API.

For example:

curl --header 'Authorization: Basic d2VibG9naWM6d2VsY29tZTE=' \
--header 'Content-Type: application/json' \
--request POST 'http:<Servername>:<Port>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/oauthidentitydomain' \
--data-raw '{"name":"MyDomain","identityProvider":"UserIdentityStore1","description":"MyDomain",
"tokenSettings":[{"tokenType":"ACCESS_TOKEN","tokenExpiry":3600,"lifeCycleEnabled":false,"refreshTokenEnabled":false,"refreshTokenExpiry":86400,"refreshTokenLifeCycleEnabled":false}],
"errorPageURL":"/oam/pages/error.jsp","consentPageURL":"/oam/pages/consent.jsp",
"customAttrs":"{\"domainCertValidityInDays\":\"30\", \"consentExpiryTimeInMinutes\":\"10\"}"}
'

where, consentExpiryTimeInMinutes in minutes is the duration, during which the OAuth consent stays valid.

Beyond this duration, OAM presents the consent page again during the 3-legged OAuth flow, and you must grant the consent.

OAM allows each of the OAuth Identity Domains to enable, disable, or change the consent validity period using consentExpiryTimeInMinutes.

To enable Consent Management for all the OAuth Identity Domains, add consentExpiryTimeInMinutes system property while starting OAM.
  1. Stop all the Administration and Managed Servers.
  2. Edit the $OAM_DOMAIN_HOME/bin/setDomainEnv.sh, and add the consentExpiryTimeInMinutes property under EXTRA_JAVA_PROPERTIES as shown
    EXTRA_JAVA_PROPERTIES="-DconsentExpiryTimeInMinutes=10"
  3. Start the Administration and Managed Servers.

Note:

System property overrides the individual Consent Management configuration on each OAuth Identity Domains.

See Also, REST API for OAuth in Oracle Access Manager.

39.2.2.1 Changing Default Consent Acknowledgment Expiry Time

You can change the default expiry time to acknowledge the consent. Alter the default expiry time by setting the custom attribute consentAcknowledgeExpiryTimeInSeconds using the OAuth Admin Identity Domain create/update API.

For example:
curl --header 'Authorization: Basic d2VibG9naWM6d2VsY29tZTE=' \
--header 'Content-Type: application/json' \
--request POST 'http:<Servername>:<Port>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/oauthidentitydomain' \
--data-raw '{"name":"MyDomain","identityProvider":"UserIdentityStore1","description":"MyDomain",\
"customAttrs":"{\"consentExpiryTimeInMinutes\":\"10\",\"consentAcknowledgeExpiryTimeInSeconds\":\"120\"}"}
where consentAcknowledgeExpiryTimeInSeconds in seconds is the maximum duration for which the user can wait before clicking the 'Allow' button on the consent screen.

Note:

See the Identity Domain REST Endpoints documentation for details about the properties.

39.2.3 Creating a Resource

A Resource Server hosts protected resources. The resource server is capable of accepting and responding to protected resource requests using access tokens.

The important parameters used in the curl command to create a resource are:
  • Name: Name of the Resource Server

  • Scopes: The following two parameters are used
    • scopeName - Name of the scope

    • description - Description of the scope

  • idDomain - Name of the IdentityDomain under which this resource server is created

  • tokenAttributes - List of custom attributes that are sent by the server, as part of the access token. The attributes can be "STATIC" in which case the value is substituted as is. If "DYNAMIC", the attributeValue is evaluated and populated in the final AccessToken.

    Note:

    Scopes are referred to by prefixing the resource server name. This makes them unique across resource servers. 

Endpoint for CRUD operations:

http:<AdminServerHost:Port>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/application

Note:

Use Content-Type:application/json in the REST API HTTP request. 
  1. A sample curl command to create a resource using scopes is shown below.
    {"name":"ResServer1","description":"TestResourceServer","scopes":[{"scopeName":"scope1","description":"ViewPage"},{"scopeName":"scope2","description":"UpdatePage"},{"scopeName":"scope3","description":"ModifyPage"}],"tokenAttributes":[{"attrName":"sessionId","attrValue":"$session.id","attrType":"DYNAMIC"},{"attrName":"resSrvAttr","attrValue":"RESOURCECONST","attrType":"STATIC"}],"idDomain":"TestDomain1","audienceClaim":{"subjects":["ab0"]}}

    For more information on OAuth REST APIs, See REST API for OAuth in Oracle Access Manager.

39.2.4 Creating a Client

A Client is an application making protected resource requests on behalf of the resource owner and with the resource owner's authorization.

The important parameters used in the curl command to create a client are:
  • Name: Name of the client

  • idDomain: Name of the identityDomain under which the client is created

  • secret: Client secret incase of a CONFIDENTIAL_CLIENT

  • clientType: Type of client. Supported values - CONFIDENTIAL_CLIENT, PUBLIC_CLIENT, MOBILE_CLIENT

  • redirectURIs: List of redirectURIs configured for the client

  • attributes: List of custom attributes configured for the client

  • grantTypes: List of allowed grant types. Allowed values - PASSWORD, CLIENT_CREDENTIALS, JWT_BEARER, REFRESH_TOKEN, AUTHORIZATION_CODE

  • Scopes: List of scopes that the client can request access to.
    • scopeName - Name of the scope. This is referred to by the <ResourceServerName>.<ScopeName>

  • defaultScope - This is the default scope that the access token is generated with, If no scope is specified during the Runtime Flows.

Endpoint for CRUD operations:

http:<AdminServerHost:Port>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/client

Note:

Use Content-Type:application/json in the REST API HTTP request. 
  1. A sample curl command to create a client using scopes is shown below.
    {"attributes":[{"attrName":"customeAttr1","attrValue":"CustomValue","attrType":"static"}],"secret":"welcome1","id":"TestClient","scopes":["ResServer1.scope1"],"clientType":"CONFIDENTIAL_CLIENT","idDomain":"TestDomain1","description":"Client Description","name":"TestClient","grantTypes":["PASSWORD","CLIENT_CREDENTIALS","JWT_BEARER","REFRESH_TOKEN","AUTHORIZATION_CODE"],"defaultScope":"ResServer1.scope1","redirectURIs":[{"url":"http://localhost:8080/Sample.jsp","isHttps":true}]}

    For more information on OAuth REST APIs, See REST API for OAuth in Oracle Access Manager.

39.3 Enabling User Lock Validation

You must enable the user lock validation to invalidate the tokens when the user is locked or disabled.

If the user is locked or disabled, the OAuth user validation flow fails. OAuth user validation is performed during OAuth authorization grant, JWT bearer grant, refresh token grant, and access token validation flows.

For example, enabling the user lock validation ensures that the access tokens (using refresh tokens) are not issued for the locked or disabled user.

Prerequisite

Before you proceed, perform the following steps to verify if the LDAPNoPasswordValidationSchemeOAuth Authentication Scheme exists:
  1. Log in to the Oracle Access Management Console.
  2. In the Oracle Access Management Console, on the top-right, click Application Security
  3. From the Application Security Launch Pad, under Access Manager, click Authentication Schemes
  4. Specify the name LDAPNoPasswordValidationSchemeOAuth and click Search.
  5. Based on whether the search returns the authentication scheme, following one of the following:

39.3.1 Enabling User Lock Validation if LDAPNoPasswordValidationSchemeOAuth Exists

To enable user lock validation perform the following steps:

  1. Log in to the Oracle Access Management Console.
  2. In the Oracle Access Management Console, on the top-right, click Configuration.
  3. Click User Identity Stores
  4. Under OAM ID Stores, select your user identity store and click Edit.
  5. Check the box beside Use Native ID Store Settings.
  6. Under Password Management, check the box beside Enable Password Management.

For more information about these parameters, see User Identity Store Settings

39.3.2 Enabling User Lock Validation if LDAPNoPasswordValidationSchemeOAuth Does Not Exist

To enable user lock validation perform the following steps:

  1. Follow the steps provided in Enabling User Lock Validation if LDAPNoPasswordValidationSchemeOAuth Exists
  2. Create a new Authentication Scheme (for example, LDAPNoPasswordValidationSchemeOAuth. The name can be any string):
    1. In the Oracle Access Management Console, on the top-right, click Application Security
    2. From the Application Security Launch Pad, under Access Manager, click Authentication Schemes
    3. From the drop-down for Authentication Module, select PasswordPolicyValidationModuleOAuth

      Note:

      PasswordPolicyValidationModuleOAuth is available out-of-the-box with OAM installation.
    4. Set the challenge parameter noAuthnCheckForPwdManagement=true in the authentication scheme.
    5. Set the other parameters in the authentication scheme. For example, the following figure shows a Sample Authentication Scheme Page:Authentication Scheme for User Lock Validation
  3. Update the Authentication Policy with the new scheme created:
    1. From the Application Security Launch Pad, under Access Manager, click Application Domains
    2. Click Search, and under the Search Results, click IAM Suite
    3. In IAM Suite Application Domain, click the Authentication Policies tab and click OAuth Assertion Policy
    4. From the drop-down for Authentication Scheme, select the new scheme that you have created. For example, LDAPNoPasswordValidationSchemeOAuth
    5. Click Apply.

39.4 Enabling User Password Change Validation

You must enable the user password change validation to invalidate the tokens that were generated before the user password update.

If the user changes/updates the password after retrieving the token, then those tokens are marked as invalid and the user must regenerate them.

Note:

To enable this validation, the user must set the userPasswordChangeCheckEnabled=true property in oam-config.xml.

Following are the steps to enable user password change validation.
  1. Check if OAuthConfig exists.
    curl --location --request GET 'http://<AdminServerHost>:<AdminServerPort>/iam/admin/config/api/v1/config?path=%2FDeployedComponent%2FServer%2FNGAMServer%2FProfile%2Fssoengine%2FOAuthConfig' \
    --header 'Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=' \

    Response

    1. If OAuthConfig does not exist: 422 Unprocessable Entity (WebDAV) (RFC 4918)
    2. If OAuthConfig exists: 200
      <Configuration xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsd:schemaLocation="http://higgins.eclipse.org/sts/Configuration Configuration.xsd" Path="/DeployedComponent/Server/NGAMServer/Profile/ssoengine/OAuthConfig">
          <Setting Name="OAuthConfig" Type="htf:map">
              <Setting Name="ClientSecretRecoveryEnabled" Type="xsd:boolean">true</Setting>
          </Setting>
      </Configuration>
    1. If OAuthConfig does not exists, then set the OAuthConfig to enable the userPasswordChangeCheck feature.
      curl --location --request PUT 'http://<AdminServerHost>:<AdminServerPort>/iam/admin/config/api/v1/config?path=%2FDeployedComponent%2FServer%2FNGAMServer%2FProfile%2Fssoengine%2FOAuthConfig' \
      --header 'Content-Type: application/xml' \
      --header 'Access-Control-Request-Headers: application/xml' \
      --header 'Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=' \
      --data '<Setting Name="OAuthConfig" Type="htf:map" Path="/DeployedComponent/Server/NGAMServer/Profile/ssoengine/OAuthConfig"> <Setting Name="userPasswordChangeCheckEnabled" Type="xsd:boolean">true</Setting></Setting>'
    2. If OAuthConfig exists, then append the existing settings to the request body.
      curl --location --request PUT 'http://<AdminServerHost>:<AdminServerPort>/iam/admin/config/api/v1/config?path=%2FDeployedComponent%2FServer%2FNGAMServer%2FProfile%2Fssoengine%2FOAuthConfig' \
      --header 'Content-Type: application/xml' \
      --header 'Access-Control-Request-Headers: application/xml' \
      --header 'Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=' \
      --data '<Setting Name="OAuthConfig" Type="htf:map" Path="/DeployedComponent/Server/NGAMServer/Profile/ssoengine/OAuthConfig"> <Setting Name="ClientSecretRecoveryEnabled" Type="xsd:boolean">true</Setting> <Setting Name="userPasswordChangeCheckEnabled" Type="xsd:boolean">true</Setting></Setting>'

    Note:

    PUT using /iam/admin/config/api/v1/config replaces the existing configuration with new values, make sure you cross-check the existing configuration using a GET before updating the configuration using the PUT API. For details on:
  2. Once the feature is enabled, OAM will no longer accept tokens generated before the password was updated and tokens must be regenerated in such cases.

39.5 Enabling Consent Management on MDC

Follow the steps in this section to enable Consent Management on MDC.

Note:

To enable consent managemet for a pre-existing MDC configuration, you must re-configure MDC.
  1. Setup two OAM environments DC1 (Master) and DC2 (Clone).
  2. Set the consentExpiryTimeInMinutes parameter in the OAuth Identity Domain on the Master. For details, see Enabling Consent Management.
  3. Configure OAuth on the Multi-Data Centers. For details, see Configuring OAuth in Multi-Data Centers
  4. Enable Automated Policy Syncronization. For details, see Enabling Automated Policy Synchronization

39.6 Configuring OAuth in Multi-Data Centers

You can configure OAuth support in Multi-Data Centers(MDC) using REST APIs.

The following scenario illustrates the flow to configure OAuth in an MDC environment using REST APIs. Perform the following procedures in the sequence given here:.
  1. Create the OAuth Artifacts - Identity Domain, Resource Server, Client and associated trust artifacts on the MasterDC. 

  2. Follow the steps given in Configuring Multi-Data Centers to setup MDC between two data centers.

    Note:

    As part of Step 2, the requests exportAccessStore on Master and importAccessStore on Clone DC are performed. This ensures that artifacts created on MasterDC are visible on CloneDC. Step 2, also ensures that the OAuth Artifacts get copied over to the Clone DC.

  3. Perform GET commands of these artifacts on the Clone DC to confirm that OAuth has been successfully setup in MDC mode.

  4. Enable Automated Policy Synchronization

  5. Now execute the 2 legged flows to verify MDC flows.

    1. Create an Access Token as part of Password Grant Flow on DC1.

    2. Send the same token to the Clone DC end point for validation.

    3. The token should be valid on DC2.

39.7 Optional Parameters for Consent Management in Multi-Data Centers

You can set the following optional parameters in the system property of the Runtime Server on the Clone Data Center.

  1. Stop all the Administration and Managed Servers.
  2. Edit the $OAM_DOMAIN_HOME/bin/setDomainEnv.sh and add the parameters under EXTRA_JAVA_PROPERTIES.
    For example,
    EXTRA_JAVA_PROPERTIES="-DconsentExpiryTimeInMinutes=10"
  3. Start the Administration and Managed Servers.

Table 39-2 Optional Parameters for Consent Management on MDC

Parameter Default Value Description
failOnConsentStoreError true

By default, if master DC is not available, the user consent request is not processed and an error is displayed to the user.

To turn off the error, set the value of the parameter to false. However, the error will exist in the logs.

printEntitiesInRequest false Prints the body of HTTP request and response to the log.
runtimeResourceConnTimeout 60000 (in milliseconds; 60 seconds) Specifies the connection timeout for the HTTP Request to store/fetch/delete entities to the Master DC.
runtimeResourceReadTimeout 60000 (in milliseconds; 60 seconds) Specifies the HTTP response read timeout from the Master DC.
sourceDcJournalThreshold 100 Defines the limit for on-demand replication from the runtime server.

After this limit, the on-demand replication sets in and all the user requests also try to fetch the results from Master.

sourceDcJournalThresholdUpperLimit 250 Defines the upper limit for on-demand replication.

If the Journal Sequence difference between the Clone DC and Master DC grows beyond the defined limit, the OAMRE-07023 error is displayed to the administrators for all user requests.

sourceDcLastPingThresholdInSec 600 (in seconds; 10 minutes) Defines the limit for availability of the Master.

If the last ping to the Master is successful within this time limit, the master is considered available.

You must always set the value of this parameter greater than the value of sourceHealthCheckIntervalInSec

sourceHealthCheckIntervalInSec 120 (in seconds; two minutes) Specifies the polling frequency for checking the connection and the latest journal sequence in Master DC.
replication.poller.thread.interval 120 (in seconds; two minutes) Running Replication on Policy Manager can result into multiple instances due to Policy Manager cluster. Replication Instance Manager Thread ensures that a single instance of Replication is running in a clustered environment.

This parameter defines the interval, in which Replication Instance Manager Thread must run.

replication.database.thread.interval 120 (in seconds; two minutes) Single replication instance on Policy Manager Cluster is maintained by having an entry in database and continuously updating it. Every cluster keeps performing the insert or update operation.

This parameter determines a valid database entry duration, that is, if an instance has updated the database entry within the duration, for example, 2 min, then the other instances cannot override it.

But if the instance fails to update the entry, other instances can update the database entry post the duration.

39.8 Error Codes and Troubleshooting Steps for Consent Management on MDC

The section lists the error codes and the troubleshooting steps for consent management on MDC.

Error Code Error Description Resolution
OAMRE-07001 Error is logged in the Master DC if the user data has been modified but the deleted data is still present in the main store. Manually delete the runtime data identified by the unique id present in the log.
OAMRE-07002 , OAMRE-07018, OAMRE-07019

Error is logged in the Clone DC when there are multiple replication agreements pointing to the same Master DC.

There must be only one replication agreement from Master DC (Source DC) and Clone DC(target DC).

Remove the multiple replication agreeements using the replication agreement Rest APIs.

OAMRE-07004 Error occurs if the replication agreement has been modified and deleted, and the older replication agreement is no longer valid. Restart the managed servers in Clone DC.
OAMRE-07006 Error occurs if the Master DC replication API does not work or the current replication agreement is not valid. Restart the managed servers in Clone DC.
OAMRE-07008 Error is logged if MDC has been setup without the Policy Manager REST endpoint. Add the Policy Manager REST endpoint, in the MDC configuration, with the name PolicyManagerRESTEndpoint
OAMRE-07009 Error is logged if the Replication Agreement is not present and/or the replication agreement does not have the authorization code using which the master can be connected. Ensure the replication agreement exists with necessary authorization code.
OAMRE-07010 , OAMRE-07011, OAMRE-07012, OAMRE-07013 , OAMRE-07016, OAMRE-07020, OAMRE-07022 Error is logged in the Clone DC when the Master DC resources are not present and/or Master DC is not available. Check if the Master DC resource is available and if the Master DC has been patched correctly.
OAMRE-07014, OAMRE-07015, OAMRE-07016 Error occurs if there is missing entity in the Master DC. Delete the entity from the clone DC.
OAMRE-07017 Error occurs if the source server (Master DC) setting does not exist in the confirguration. Check the Entity replication or Import and Export the access store again and redo the Entity and Runtime Entity Replication.
OAMRE-07023 Error occurs if the runtime entity replication is out-of-sync and the journal backlog for replication has grown beyond the value of sourceDcJournalThresholdUpperLimit parameter. This gets auto corrected once the runtime entity replication gets in sync.

Manually Import access store and Export access store to synchronize the data again.

Error in the clone processing server response. Enable the HTTP request and response log by setting the system property printEntitiesInRequest=true Request and response Logging is enabled by setting this property.

39.9 Dynamic Client Registration

Dynamic client Registration (DCR) provides a way for the native mobile apps (Android) to dynamically register as clients with the OAuth Server (OAM).

This section provides the detailed process for dynamically registering clients with the Oauth Server (OAM).

  1. Enabling Dynamic Client Registration
  2. Creating OAuth Client Template
  3. Getting Registration Tokens
  4. Registering the Client using the Registration Token
  5. Reading Client Details

39.9.1 Enabling Dynamic Client Registration

You must enable Dynamic Client Registration (DCR) at the identity domain level.

Create an Identity domain with the custom attribute isDcrRegEnabled set to true using the Admin Server OAuth API, as shown.

Note:

If the isDcrRegEnabled flag is not specified, or set to false then DCR is disabled.
curl -X POST \
 http(s)://<Admin-Server-URL>:<Admin_Server_Port>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/oauthidentitydomain \
-H 'authorization: Basic d2VibG9naWM6d2VsY29tZTE=' \
-H 'cache-control: no-cache' \
-H 'content-type: application/json' \
-d '{"name":"dcr_domain","enableMultipleResourceServer":false,"description":"DCR Domain",
"tokenSettings":[{"refreshTokenEnabled":true,"refreshTokenLifeCycleEnabled":true,"refreshTokenExpiry":5400,
"lifeCycleEnabled":true,"tokenType":"ACCESS_TOKEN","tokenExpiry":1800},
{"refreshTokenEnabled":true,"refreshTokenLifeCycleEnabled":true,"refreshTokenExpiry":10800,
"lifeCycleEnabled":true,"tokenType":"AUTHZ_CODE","tokenExpiry":240}],
"customAttrs":"{\"isDcrRegEnabled\":\"true\"}"
}'

39.9.2 Creating OAuth Client Template

The OAuth client template serves as a blueprint for creating the actual clients.

Create the OAuth client template using the Admin Server OAuth API, as shown.

curl -X POST \
http(s)://<AdminServerHost:Port>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/client \
  -H 'authorization: Basic d2VibG9naWM6d2VsY29tZTE=' \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -d '{"id":"DCR_REG_STUB_oma", "secret":"welcome1",
"redirectURIs": [{"url":"http://www.dcr.com/access","isHttps":"false"}],
"scopes":["dcrreg"],"grantTypes":["IMPLICIT"],"clientType":"PUBLIC_CLIENT","idDomain":"dcr_domain",
"description":"dcr client for acme app registration","name":"DCR_REG_STUB_acme","defaultScope":"dcrreg"}'

Table 39-3 Mandatory Property and Values for Creating the OAuth Client Template

Property Values
grantTypes IMPLICIT.
clientType PUBLIC_CLIENT
idDomain Must be the same as the domain under which the actual clients need to be created.
name Must be prefixed with DCR_REG_STUB_.

Note:

The prefix must not be used in regular client names.
defaultScope dcrreg

Note:

The scope field must contain only one scope and its value must be dcrreg.
redirectURIs Specify the URIs as required by the actual client.

Note:

The redirectURI values are automatically assigned to the actual client.

39.9.3 Getting Registration Tokens

The mobile device apps that need to register dynamically with the Oauth Server (OAM) must first acquire the registration token.

Dynamic Client Registration (DCR) must be enabled and the Oauth Client Template must be created.

Process Flow for Getting Registration Token

  1. User opens native app on the mobile device
  2. The native app displays Register button
  3. When the user clicks on the Register button, the app launches the browser with registration token URI. The request to the OAuth Server includes domain_name and template_id.
  4. Based on the authentication policy configured, the user is redirected to the login form.
  5. After successful authentication, OAuth Server generates the registration token and returns it as a token or qrcode, based on the request.
  6. Using the registration token, the native app can continue to register the client.

Figure 39-1 Diagram Showing the Flow for Getting Registration Token

Diagram Showing the Flow for Getting Registration Token

Registration Token Sample Request

On the mobile device, when the user (or resource-owner) opens the app, the app must send a GET request with /dcr/token endpoint to the Oauth Server (OAM). The /dcr/token endpoint must be protected.

The following is a request sample

GET http(s)://<server-host>:<server-port>/oauth2/rest/dcr/token?domain=dcr_domain&template_id=DCR_REG_STUB_acme&response_type=token

Table 39-4 Registration Token Sample Response

Configuration Sample Response

Redirect URI is defined in the Client Template.

In this case response_type parameter if passed is ignored.

<redirect_uri from template>?access_token=<registration access token value>
Redirect URI is not present and response_type is not passed, or passed as token.
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-cache
Pragma: no-cache
{
  "access_token":"token value",
  "token_type":"Bearer",
  "expires_in":1800
}
Redirect URI is not present and response_type is passed as qrcode
HTTP/1.1 200 OK
Content-Type: image/png
Cache-Control: no-cache
Pragma: no-cache
<QR Code Image in png format>
The following table shows the responses in case of errors:

Table 39-5 Registration Token Error Responses

Scenario HTTP Status Code Errror Message Secondary Message
OAuth Service is not enabled 403 Unauthorized Unauthorized
Dynamic Client Registration is not enabled 403 Unauthorized Unauthorized
Required fields are not provided 400 Invalid Request Required fields are missing
Invalid Domain 400 Invalid Request Invalid Domain
Invalid Client:
  • Name does not have the prefix DCR_REG_STUB_
  • Client passed doesn't exist
400 Invalid Request Invalid Client
Invalid Response Type 400 Invalid Request Unsupported Response Type
Client passed is not authorized to execute DCR flow 403 UnAuthaorized Client UnAuthorized Client

39.9.4 Registering the Client using the Registration Token

Use the registration token to register the clients with the OAuth Server (OAM).

Process Flow for Client Registration

  1. The native app sends a request containing the registration token to OAuth Server for registering the client.
  2. OAuth Server validates the token and registers the client. The client profile includes the following fields:

Figure 39-2 Diagram Showing the Flow for Client Registration

Diagram Showing the Flow for Client Registration

Client Registration Sample Request

The application must use the POST method with /dcr/client to register as client.

POST /oauth2/rest/dcr/client HTTP/1.1
Host: <OAuth Server host-name>:<OAuth server port name>
Content-Type: <can be any valid value as there is no input>
X-OAUTH-IDENTITY-DOMAIN-NAME: dcr_domain
Authorization: Bearer eyJraWQiOi.abcdsfsdfr.ascsfsdff

Client Registration Sample Response

HTTP/1.1 201 Created 
Content-Type: application/json
Cache-Control: no-cache 
Pragma: no-cache 
{
 "client_id": "cd885f3da58f498e830c4f636636dd23",
 "client_secret": "gjDmqUVW1k",
 "client_name": "oma498e830c4f636636dd23",
 "redirect_uris": [
     "app://callBack"
   ],
 "client_secret_expires_at": 0,
 "client_get_uri": "http(s)://<host>:<port>/oauth2/dcr/client?client_id=<id of created client>"
}
The following table shows the responses in case of errors:

Table 39-6 Client Registration Error Responses

Scenario HTTP Status Code Errror Message Secondary Message
OAuth Service is not enabled 403 Unauthorized Unauthorized
Dynamic Client Registration is not enabled 403 Unauthorized Unauthorized
Required fields are not provided 400 Invalid Request Required fields are missing
Invalid Domain 400 Invalid Request Invalid Domain
Invalid Token 401 Unauthorized Access token is {0} , where {0} could be:
  • expired
  • malformed
  • invalid
  • revoked
Fails on server 500 Internal Server Error Detailed error message on what went wrong
Client already exists 409 Client already exists Client already exists

39.9.5 Reading Client Details

Read APIs are protected using OAuth. This section provides details on how to read client information.

Generate the authorization code, for the client that needs to be read, using scope=dcrread as shown in the following sample request.

http(s)://<server-host>:<server-port>/oauth2/rest/authz?response_type=code&client_id=cd885f3da58f498e830c4f636636dd23&domain=dcr_domain
&scope=dcrread&state=xyz&redirect_uri=http://www.dcr.com/access

Pass this authorization code to the POST method with the /oauth2/rest/token endpoint to generate the access token with scope=dcrread.

Pass this access token as bearer access token using the GET method with the /dcr/client endpoint to read the client.

Sample Request for Retreiving Client Details

GET /oauth2/rest/dcr/client/cd885f3da58f498e830c4f636636dd23  HTTP/1.1
Host: <OAuth Server host-name>:<OAuth server port name>
Content-Type: <can be any valid value as there is no input>
X-OAUTH-IDENTITY-DOMAIN-NAME: dcr_domain
Authorization: Bearer <Access token>
Sample Response
{
    "client_id": "cd885f3da58f498e830c4f636636dd23",
    "domain": "domainName",
    "client_name": "oma498e830c4f636636dd23",
    "redirect_uris": [
        "http://www.dcr.com/access", "other redirect URI"
    ]
}

39.9.6 Deleting Dynamically Registered Client

This section provides details on how to delete the dynamically registered client.

Generate the authorization code, for the client that needs to be deleted, using scope=dcrdel as shown in the following sample request.

http(s)://<server-host>:<server-port>/oauth2/rest/authz?response_type=code&client_id=cd885f3da58f498e830c4f636636dd23&domain=dcr_domain
&scope=dcrdel&state=xyz&redirect_uri=http://www.dcr.com/access

Pass this authorization code to the POST method with the /oauth2/rest/token endpoint to generate the access token with scope=dcrdel.

Pass this access token as bearer access token using the DELETE method with the /dcr/client endpoint to delete the client.
GET /oauth2/rest/dcr/client/cd885f3da58f498e830c4f636636dd23  HTTP/1.1
Host: <OAuth Server host-name>:<OAuth server port name>
Content-Type: <can be any valid value as there is no input>
X-OAUTH-IDENTITY-DOMAIN-NAME: dcr_domain
Authorization: Bearer <Access token>

39.10 SSO Session Linking for OAuth Tokens

In deployment scenarios where a few resources are protected by OAM while some might be accessed with OAuth, to achieve seamless SSO between the different mixes of applications, it is necessary to link the SSO session with the Access Token. SSO Session Linking for OAuth Tokens supports key OAuth deployments requiring 2 legged flows involving native mobile apps and Synchronization of OAuth Tokens with SSO tokens.

Use Case Flow

Figure 39-3 illustrates the use case flow of the SSO Ssession linking.

Figure 39-3 Use case flow for SSO Session Linking for OAuth Tokens

Description of Figure 39-3 follows
Description of "Figure 39-3 Use case flow for SSO Session Linking for OAuth Tokens"

Server Changes to Link SSO Session

SSO Linked JWT Token Creation
  1. When the SSO Session is created, a JWT User Token is also created. The JWT User Token has the SSO "session_id" as part of its claims. 

  2. Creating this JWT Token is based on configurations. When created, this token can be sent either as a cookie or a header to downstream applications. Currently the configurations are set as challenge parameters at the scheme level.

    By default, the SSO link JWT token is set in the cookie.

    Note:

    If the OAUTH_TOKEN_RESPONSE_TYPE is header, the JWT token is set with the cookie name JWTAssertion.

    If the OAUTH_TOKEN_RESPONSE_TYPE is cookie, the JWT token is set with the cookie name OAUTH_TOKEN.

    Description of ssolink_challengparam.png follows
    Description of the illustration ssolink_challengparam.png
  3. Token Signing: On bootstrap a default OAuth key-certificate is boot-strapped into the server. The JWT token will be signed by the Identity Domain private key. When the JWT token is received as an assertion back, the X5T value is retrieved from the header and the associated public key is fetched, which can be used to verify the token.

SSO Linked JWT Token Validation
  1. When the token is sent back as part of the JWT Bearer flow in the OAuth Token request, the OAM server retrieves theSSO "session_id" from the token.

  2. Check Valid Session: If the JWT Token has a session ID, the server knows this is a SSO Linked JWT Token. It retrieves the "sessionId" claim from the token and checks if the server session with the given ID is still valid.

  3. If the session is valid, the subject from the SSO Session is compared with the “sub” field in the JWT Token. If this matches, the access token for this user is generated and returned to the client.

SSO Linked JWT Token Validation in MDC Flows
  1. In case of an MDC Enabled environment, as part of the JWT Token creation, another claim "mdc_sso_link" is also added to the token. This claim contains the clusterId of the machine on which the session was anchored and the UserIdentityStore reference 

  2. When the token is sent back as part of the JWT Bearer flow in the OAuth Token request, the OAM server will retrieve the SSO Session ID from the token.

  3. Check Valid Session: If the JWT Token has a session ID, the server knows this is a SSO Linked JWT Token. It retrieves the "sessionId" claim from the token and the clusterid from the mdc_sso_link claim and retrieves the session. The normal MDC flows for checking validity of the session are maintained here.

  4. If session is valid, the subject from the SSO Session will be compared with the “sub” field in the JWT Token. If this matches, the access token for this user is generated and the returned to the client.

Session IdleTimeOut and the SSO Linked Token 

If the session has been idle for more than 15 mins(configured value), when this JWT token is checked for validity it will fail. This ensures that the rules of the session are also applied to the OAuth Access Tokens.

39.11 Runtime REST APIs for OAuth 12c

Runtime REST APIs for OAuth provides REST calls for 2-legged and 3-legged OAuth Services flows in the new 12c OAuth Server. The sections provide sample REST requests that show how to get a resource access token.

Creating Access Tokens

The new end point is:
http://<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token
2 - Legged Flows
  1. Using Resource Owner Credentials

    Following is a sample request against the server: 

    curl -i -H 'Authorization: Basic U1NPTGlua0NsaWVudDp3ZWxjb21lMQ==' -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8" -H "X-OAUTH-IDENTITY-DOMAIN-NAME: SSOLink" --request POST http://<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token -d 'grant_type=PASSWORD&username=weblogic&password=welcome1&scope=SSOLink.link1'

    Note:

    Headers of interest for all requests
    • Authorization : Base64 Url encoded ClientID:secret combination. 

    • X-OAUTH-IDENTITY-DOMAIN-NAME: Identity Domain that the client belongs to.

    • From 12.2.1.4.5 onwards, identity domain can be provided as query parameter identityDomain instead of the header paremeter X-OAUTH-IDENTITY-DOMAIN-NAME.

  2. Using Client Credentials

    Following is a sample request against the server: 

    curl -i -H 'Authorization: Basic U1NPTGlua0NsaWVudDp3ZWxjb21lMQ==' -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8" -H "X-OAUTH-IDENTITY-DOMAIN-NAME: SSOLink" --request POST http://<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token -d 'grant_type=CLIENT_CREDENTIALS&scope=SSOLink.link1'
  3. Using JWT Bearer Token

    Following is a sample request against the server: 

    curl -i -H 'Authorization: Basic U1NPTGlua0NsaWVudDp3ZWxjb21lMQ==' -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8" -H "X-OAUTH-IDENTITY-DOMAIN-NAME: SSOLink" -- request POST http://<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token -d 'grant_type=JWT_BEARER&scope=SSOLink.link1&assertion=<assertion token value>'
    • Using JWT Bearer Flow to get User Data through UserInfo Endpoint

      If an access token got from the JWT bearer flow is required to fetch user data through /UserInfo endpoint, the following scopes have to be assigned to the client and requested during runtime.

      Scope Corresponding OpenID Scope
      UserInfo.email openid email
      UserInfo.me (default) openid

      (returns the username)

      UserInfo.address openid address
      UserInfo.phone openid phone
      UserInfo.profile openid profile

      Client Profile

      Following is a sample client profile, which is registered with the UserInfo related scopes.

      curl -X POST \
       http://<AdminServerHost:Port>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/client \
       -H 'Authorization: Basic d2VibG9naWM6d2VsY29tZTE=' \
       -H 'Content-Type: application/json' \
       -d '{"attributes":[{"attrName":"UserAttr","attrValue":"CustomStaticValue","attrType":"STATIC"},
      			  {"attrName":"ResServerConstAttr","attrValue":"Overriding client - static attribute","attrType":"STATIC"}],
      "secret":"welcome1","id":"DemoClientID","scopes":["UserInfo.address", "UserInfo.email"],"clientType":"CONFIDENTIAL_CLIENT","idDomain":"DemoDomain","description":"Client Description","name":"DemoClient","grantTypes":["JWT_BEARER"],"defaultScope":"UserInfo.email","redirectURIs":[{"url":"http://localhost:8080/Sample.jsp","isHttps":true}]}'

      Example

      Following is an example of the token request.

      curl -i -H 'Authorization: Basic U1NPTGlua0NsaWVudDp3ZWxjb21lMQ==' -H "Content- Type: application/x-www-form-urlencoded;charset=UTF-8" -H "X-OAUTH-IDENTITY- DOMAIN-NAME: SSOLink" -- request POST http://<ManagedServerHost:ManagedServerPort>/oauth2/rest/token - d 'grant_type=JWT_BEARER&scope=UserInfo.email UserInfo.address&assertion=assertion token value'
  4. Using Refresh Token

    Following is a sample request against the server: 

    curl -i -H 'Authorization: Basic U1NPTGlua0NsaWVudDp3ZWxjb21lMQ==' -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8" -H "X-OAUTH-IDENTITY-DOMAIN-NAME: SSOLink" --request POST http://<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token -d 'grant_type=REFRESH_TOKEN&scope=SSOLink.link1&refresh_token=<RefreshTokenValue>'
  5. Using Resource Owner Credentials with JWT - Client Assertion Token

    Following is a sample request against the server: 

    curl -i -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8" -H "X-OAUTH-IDENTITY-DOMAIN-NAME: SSOLink" --request POST http://<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token -d 'grant_type=PASSWORD&scope=SSOLink.link1&client_assertion=<ClientAssertionTokenValue>&client_assertion_type=JWT_BEARER&username=weblogic&password=welcome1'

Note:

  • Allowed values for client_assertion_type are JWT_BEARER andurn:ietf:params:oauth:client-assertion-type:jwt-bearer 

  • redirect_uri is not expected for 2 legged flows.

  • scope is optional in 2 legged flows. If not provided, the access token will be generated with the defaultScope associated with the client (provided during client registration).

3 - Legged Flows — process

In order to achieve 3–legged flow, you need to perform few manual steps both on the OAM server and on the Webgate before proceeding. The consent page and approver page need to be protected through OAM. If the consent page is customized, this needs to be protected by a Webgate.

  • OAM server - On the created Application Domain, you need to add couple of 3 legged resources as described in the given steps.

  • Webgate - Modify the mod_wl_ohs.conf as mentioned in this section.

OAM Server side steps to be performed

  1. List of all the resources to be added as part of 3 legged setup. Details for each and every resource is mentioned as in step2.

    Description of all_resources.png follows
    Description of the illustration all_resources.png
  2. Create a resource "/oauth2/rest/approval". This has to be protected by Webgate.  

    Description of 3legged11.png follows
    Description of the illustration 3legged11.png
  3. Create a resource "/oauth2/rest/approval/skip". This has to be protected by Webgate.

    A sample, illustrating the creation of resource "/oauth2/rest/approval/skip", which is protected by WebGate.
  4.  Create a resource "/oam/pages/consent.jsp" which is the out of the box consent page. If you are using a custom consent page, it needs to be protected by Webgate and the appropriate resource has to be added here.

    Description of consent_resource.png follows
    Description of the illustration consent_resource.png
  5. Create a resource "/oauth2/rest/**" and  mark the Protection level as Excluded.

    Description of 3legged3.png follows
    Description of the illustration 3legged3.png
  6. Create a resource "/oam/**" and  mark the Protection level as Excluded.

    Description of oam_resource.png follows
    Description of the illustration oam_resource.png

Webgate Side steps to be performed

Open and update the mod_wl_ohs.conf  file which is located at <OHS_HOME>/user_projects/domains/base_domain/config/fmwconfig/components/OHS/<ohs instance name> location and add the below entry.

 <Location /oauth2>       
SetHandler weblogic-handler       
WebLogicHost  <Managed Server Host Name>       
WebLogicPort  <Managed Server Port>       
ErrorPage  http:/WEBLOGIC_HOME:WEBLOGIC_PORT/   
</Location>   

<Location /oam>       
SetHandler weblogic-handler       
WebLogicHost  <Managed Server Host Name>       
WebLogicPort  <Managed Server Port>       
ErrorPage  http:/WEBLOGIC_HOME:WEBLOGIC_PORT/  
</Location>

3 Legged Flows

  1. Through the Browser request the Authorization Code

    Following is a sample request against the server

    http://<OHS Hostname>:<OHS Port>/oauth2/rest/authz?response_type=code&client_id=TestClient2&domain=TestDomain1&scope=TestRS.scope1+TestRS.scope2+TestRS.scope3&state=xyz&redirect_uri=http://localhost:8080/SampleTest/index.jsp 
  2. Generate the Access Token using the Authorization Code

    Following is a sample request against the server

    curl --request POST \ --url http://<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token --header 'authorization: Basic U1NPTGlua0NsaWVudDp3ZWxjb21lMQ==' --header 'cache-control: no-cache' --header 'content-type: application/x-www-form-urlencoded' --header 'x-oauth-identity-domain-name: SSOLink' --data grant_type=AUTHORIZATION_CODE&code=bnAreDZVMUxEemZtZmJPUEE2U1N2QT09fmVBUVJZYnFtYmZFSU1EaUFpSktvQjVwQ0ZGQm4xV1R4dmJrekp0MTdDZXdPYjJFNjEwVkdhZlN3VWJjTWcvRUpwL3RqWERUZWliZWdUSzZPQkxQNktwQk03c0ZKMEV1NmN3SmxwbGl5b1U4MnZ6S1pXRFB6ekdiU1k3V3FEZ3lLSjgxM0NwUGNwUjk1eXI5enRKb0ZLb1VVZ0hqNm53TkVFTEpKMmtKNmY3b1ZHWDFtcFkvL1haMUs4N0xiRGlnbkFwTWpHd1J5QjVuZkdxTzh4U01hamdWZnNmT3doSlo1SS9KY3NtOGNaQkJxMDd3SzgrWXBIcVYxYlgxYzFLSWhubW5MWndZQTg5ZnV0aU1Kam54bytZaGZhbW5IK2xrNjFBYVhxOHB5SEdENG5SRzJ2aytDcjRHR1g2OWZFbTdT&redirect_uri=http%3A%2F%2Fredirect_uri' 

Validating Access Tokens

curl -i -H "X-OAUTH-IDENTITY-DOMAIN-NAME: SSOLink" --request GET "http://<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token/info?access_token=<AccessToken>"

39.12 Revoking OAuth Tokens

OAM provides Runtime and Admin REST APIs for revoking OAuth Access and Refresh Tokens.

39.12.1 Revoking OAuth Tokens by OAuth Clients

OAM provides support for the OAuth clients to revoke access and refresh tokens using the grant_typehttp://<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token/revoke Runtime REST API.

  • OAM supports token revocation of only those access and refresh tokens that are generated through 3-legged OAuth flow (Authorization code flow).

    For tokens generated through 2-legged OAuth flow, there is no user consent and the client has all the information required to regenerate the tokens. If the client is compromised, it is recommended to delete the client.

    OAM returns the following error if you provide tokens generated by 2-legged OAuth flow in the request: RESPONSE CODE: 415
    {"error": "unsupported_token_type","error_description":
        "Revocation of the presented token type not supported."}
  • Consent Management must be enabled for the OAuth tokens to be revoked. If it is not enabled, OAM returns the following error: RESPONSE CODE: 500
    {
        "error": "token_revocation_without_cmlc_not_supported",
        "error_description": "Consent management must be enabled for TOKEN REVOCATION support"
    }

    For details about how to enable consent management, see Enabling Consent Management

    For details about how to enable consent management in an MDC setup, see Enabling Consent Management on MDC

  • In an MDC setup, the time taken for the OAuth token revocation to propagate to all the data centers is dependent on the value set in pollInterval. Recommended value is 5 seconds. That is, if the client revokes the OAuth tokens on one data center, it takes at least five seconds for the changes to get propagated to the other data center in the MDC topology. For more details about changing pollInterval, see Modifying the Polling Interval in Clone Data Centers

    Also, it is recommended to set the BatchSize to 300. For details, see Table 19-2

Ensure the following headers are added in the request:
  • Authorization : Base64 URL encoded <ClientID>:<Secret> combination.
  • X-OAUTH-IDENTITY-DOMAIN-NAME: Identity Domain that the client belongs to.
  • Content-Type: application/x-www-form-urlencoded: The token is provided as a key-value pair in the request body.

For more information about the parameters, response codes, error codes, and so on, see Revoke Token REST Endpoints REST API documentation.

Revoking a Specific Access or Refresh Token

OAuth clients can use the http://<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token/revoke API to revoke a specific access or refresh token.

OAM implements token revocation as defined in RFC 7009. Refer to https://tools.ietf.org/html/rfc7009 for information.

Sample Request to Revoke a Token
curl --location --request POST '<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token/revoke' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'x-oauth-identity-domain-name: DemoDomain' \
--header 'Authorization: Basic RGVtb0NsaWVudElkOndlbGNvbWUx' \
--header 'Cookie: JSESSIONID=VKgaCGYiIiQ_3-gTdIOymIqW4uMXGt2OPNglGjTvJUaVyP4gkNY3!-472705583' \
--data-urlencode 'token=eyJraWQiOiJEZW1vRG9tYWluIiwieDV0IjoiZG1HQi1zR1BlcHEzblE2ZWdyRnNkM3c4ZU9
JIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwOi8vc2xjMDdoYWYudXMub3JhY2xlLmNvbToyMjIyL29hdXRoMiIsImF1
ZCI6WyJEZW1vUmVzU2VydmVyIiwiYWIwIl0sImV4cCI6MTYxNTM1MDY3NywianRpIjoiX3BDeGRpdkNkc0F3Q2JvcHY2OHoz
USIsImlhdCI6MTYxNTM0NzA3Nywic3ViIjoidXNlckEiLCJjdXN0b21BdHRyaXNlc3Npb25JZCI6IjM4M2E0YjA3LTg4NWUt
NGIxYy05MzZhLWRjYTVlYzlmOGMyZnwvSDZ2OHZJc0NZaUR1T3l1MFN0RHVnUE1rdXQ1VUxVSUtQZGZpait0ejhnPSIsIm1k
Y19zc29fbGluayI6Ijk2YmJjLXNsYzA3aGFmLnV-flVzZXJJZGVudGl0eVN0b3JlMSIsImN1c3RvbUF0dHJpMiI6IlJFU09V
UkNFQ09OU1QiLCJjbGllbnQiOiJEZW1vQ2xpZW50SWQiLCJzY29wZSI6WyJEZW1vUmVzU2VydmVyLkRlZmF1bHRTY29wZSJd
LCJkb21haW4iOiJEZW1vRG9tYWluIiwiZ3JhbnQiOiJBVVRIT1JJWkFUSU9OX0NPREUifQ.byPaJjUfH2Pi9ipTKIaAAB5CP
B5lwLd8ga_39ruDQEfckqYcgHAToTQfFn6uibbEn0EluxJqE_rnT6ABLWQ0VABruMRRiK2fcE7qGSSWXdakjjWmYG4pVJTgN
64OrEroUPM-65ZvqIDmMiYG-80dVJpQq3QxG9_7yJhG0g8Rf1cxGITJb2_RLnl9Ke1Wmex5LcMKRGGhiezA98o_jluknmzdUi
Pw1C2NGxXESvTgMnM7Q49exnG1py-aZ7KaohF8misS2_Hbgx4f-2ipG8CQtefiwCEDvPpk30QGKuU4GGmV9yUlV3qd-yqJTUA
4EbvffsNeadSjhsov3Sjw8ZNq1g'
Sample Response

{
    "status": "success"
}

Revoking Related Consents, Access, or Refresh Tokens

If a refresh token is created along with the access token during the 3-legged OAuth flow, that refresh token can be used to generate the access tokens multiple times till the time the refresh token is valid. For more information, see OAuth Refresh Tokens

To revoke all such related refresh and access tokens, the OAuth clients can additionally use the chaining_level parameter along with the token parameter in the http://<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token/revoke API.

The following table shows the values supported in the chaining_level parameter and the corresponding behavior.

Note:

The token parameter is mandatory; however, token_type is optional. The token type is decided based on the token provided in the token parameter.

Table 39-7 chaining_level Values and Behavior

If the Specified Type of Token is ... chaining_level values Behavior
Refresh Token NONE Default. The refresh token specified in the token parameter is revoked.
  RELATED_TOKENS In addition to the refresh token specified in the token parameter, all the access tokens that were generated by that refresh token is revoked.
  RELATED_CONSENT The consent is deleted. In addition to the refresh token specified in the token parameter, all the access and refresh tokens created by the grant/consent (associated with the specified refresh token) is revoked.
Access Token NONE Default. The access token specified in the token parameter is revoked.
  RELATED_TOKENS In addition to the access token specified in the token parameter, the parent refresh token, that was used to generate the specified access token, is revoked.
  RELATED_CONSENT The consent is deleted. In addition to the access token specified in the token parameter, all the access and refresh tokens created by the grant/consent (associated with the specified access token) is revoked.

The following example shows a sample request to revoke refresh token and the access tokens generated using that refresh token.

Sample Request
curl --location --request POST '<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token/revoke' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'x-oauth-identity-domain-name: DemoDomain' \
--header 'Authorization: Basic RGVtb0NsaWVudElkOndlbGNvbWUx' \
--header 'Cookie: JSESSIONID=NysahaoNLyc13HzjEh93gJmwbY4HnMetJQY33RE8_ZdBpzpw7kdr!-472705583' \
--data-urlencode 'token=LCbzQggeRM1EMgprtKrHuQ%3D%3D%7EcsLp2lL9J03orCX0dTvBySFAXG4Yi%2BI%2FOq80
ChZzVsz1BrME2GEg9Kuk6aShduv0K%2F8Yzhs6F4RCOdXgO1uZi1u3V544Hf%2FziaoJFZGDr4UmfkLHByMTJYWTJXfR%2F
MUQkkDjffRAlox1vVjztUbhB1uKMkZWE%2FhTYHCp1pkc2zNJC7j7KQaIF%2BkNfg8GPS%2FdjeLo7i99%2B%2Bifb%2BKq
GTnaJWOr2JSm7XApoGlX9dwBzM8EHdO4IQNPYDxkvtQLajVxlRhK5ZnL3F29wBD4yOuXqg%3D%3D' \
--data-urlencode 'chaining_value=RELATED_TOKENS' \
--data-urlencode 'token_type=REFRESH_TOKEN'
Sample Response

{
    "status": "success"
}

The following example shows a sample request to revoke access token and its parent refresh token from which the access token was generated.

Sample Request
curl --location --request POST '<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token/revoke' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'x-oauth-identity-domain-name: DemoDomain' \
--header 'Authorization: Basic RGVtb0NsaWVudElkOndlbGNvbWUx' \
--header 'Cookie: JSESSIONID=VKgaCGYiIiQ_3-gTdIOymIqW4uMXGt2OPNglGjTvJUaVyP4gkNY3!-472705583' \
--data-urlencode 'token=eyJraWQiOiJEZW1vRG9tYWluIiwieDV0IjoiZG1HQi1zR1BlcHEzblE2ZWdyRnNkM3c4ZU9
JIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwOi8vc2xjMDdoYWYudXMub3JhY2xlLmNvbToyMjIyL29hdXRoMiIsImF1
ZCI6WyJEZW1vUmVzU2VydmVyIiwiYWIwIl0sImV4cCI6MTYxNTM1NTAwOSwianRpIjoiZVEtVHA1N3JUTHFUTktPaERybEpnd
yIsImlhdCI6MTYxNTM1MTQwOSwic3ViIjoidXNlckEiLCJjdXN0b21BdHRyaXNlc3Npb25JZCI6IjgxOWY5ODc0NDdjMGE1Mzg
3Mzk1Mjg5OWYzZjUzMTYzMmUxZjRlODI5ZTNmN2FmMjg2OWFhNWY5M2YyMmMyYzMiLCJjdXN0b21BdHRyaTIiOiJSRVNPVVJDR
UNPTlNUIiwiY2xpZW50IjoiRGVtb0NsaWVudElkIiwic2NvcGUiOlsiRGVtb1Jlc1NlcnZlci5EZWZhdWx0U2NvcGUiXSwiZG9
tYWluIjoiRGVtb0RvbWFpbiIsInJ0X2lkIjoiM2FmN2Q5NzEtYjAyZS00ZDI5LThlOTMtNWJhMTkzMGJkN2Y2LjE2MTUzNTEzN
jciLCJncmFudCI6IkFVVEhPUklaQVRJT05fQ09ERSJ9.HBtENqB6nIAUAlcft84o5_tSFiXP_E-tD7Ux6WyC_nO0D1m2x6l7sc
9oQO8ad1vgXV4KjSGSPnxL09pWLUPDxhwQqs15w_Py1q-SWQxrcpKqtCv-vdz_zCS3_uMsaOLQTQwYyj94tnS9TEWAkQtknDrV
4vOFhhDMVOOBPIo5h7BeDa9liSIhPjlB7wPAHJ2HX4rOhL5z2BfPS2v9QNUDuJbvKZl78BwHP80L8uDaSsh5a0XMcJGr1PQ9cd0
6bSWGTF3o9NBLWBiWnPTyq17XDxnr4rEcPrp3bV_iwuIvo0id91iu52L-NTAts0FzTv7gEz2d6lNMwgMAfBFQPWFYRQ' \
--data-urlencode 'chaining_value=RELATED_TOKENS' \
--data-urlencode 'token_type=ACCESS_TOKEN'
Sample Response

{
    "status": "success"
}

The following example shows a sample request to delete the consent and also revoke all the access and refresh tokens generated by the consent associated with the specified refresh token.

Sample Request
curl --location --request POST '<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token/revoke' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'x-oauth-identity-domain-name: DemoDomain' \
--header 'Authorization: Basic RGVtb0NsaWVudElkOndlbGNvbWUx' \
--header 'Cookie: JSESSIONID=VKgaCGYiIiQ_3-gTdIOymIqW4uMXGt2OPNglGjTvJUaVyP4gkNY3!-472705583' \
--data-urlencode 'token=LCbzQggeRM1EMgprtKrHuQ%3D%3D%7EcsLp2lL9J03orCX0dTvBySFAXG4Yi%2BI%2FOq80
ChZzVsz1BrME2GEg9Kuk6aShduv0K%2F8Yzhs6F4RCOdXgO1uZi1u3V544Hf%2FziaoJFZGDr4UmfkLHByMTJYWTJXfR%2F
MUQkkDjffRAlox1vVjztUbhB1uKMkZWE%2FhTYHCp1pkc2zNJC7j7KQaIF%2BkNfg8GPS%2FdjeLo7i99%2B%2Bifb%2BKq
GTnaJWOr2JSm7XApoGlX9dwBzM8EHdO4IQNPYDxkvtQLajVxlRhK5ZnL3F29wBD4yOuXqg%3D%3D' \
--data-urlencode 'chaining_value=RELATED_CONSENT' \
--data-urlencode 'token_type=REFRESH_TOKEN'
Sample Response

{
    "status": "success"
}

Validating OAuth Token Revocation

After running the OAuth token revocation APIs, you can verify if the tokens have been successfully revoked in the following ways:

  • To verify if the refresh token has been revoked, you can use the refresh token to generate a new access token. If the refresh token has been successfully revoked, the access token generation fails. If the refresh token is still valid (not revoked) a new access token is generated.
    Sample Request
    curl --location --request POST '<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token' \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --header 'x-oauth-identity-domain-name: DemoDomain' \
    --header 'Authorization: Basic RGVtb0NsaWVudElkOndlbGNvbWUx' \
    --header 'Cookie: JSESSIONID=NysahaoNLyc13HzjEh93gJmwbY4HnMetJQY33RE8_ZdBpzpw7kdr!-472705583' \
    --data-urlencode 'grant_type=REFRESH_TOKEN' \
    --data-urlencode 'refresh_token=LCbzQggeRM1EMgprtKrHuQ%3D%3D%7EcsLp2lL9J03orCX0dTvBySFAXG4Yi%2BI%2FOq80
    ChZzVsz1BrME2GEg9Kuk6aShduv0K%2F8Yzhs6F4RCOdXgO1uZi1u3V544Hf%2FziaoJFZGDr4UmfkLHByMTJYWTJXfR%2F
    MUQkkDjffRAlox1vVjztUbhB1uKMkZWE%2FhTYHCp1pkc2zNJC7j7KQaIF%2BkNfg8GPS%2FdjeLo7i99%2B%2Bifb%2BKq
    GTnaJWOr2JSm7XApoGlX9dwBzM8EHdO4IQNPYDxkvtQLajVxlRhK5ZnL3F29wBD4yOuXqg%3D%3D'
    Sample Response
    {
        "error": "invalid_grant",
        "error_description": "Invalid Refresh Token"
    }

    Using grant_type=REFRESH_TOKEN the OAuth request will result in both the new access token as well as new refresh token.

    Likewise, the old refresh token is automatically revoked after the new access and refresh token pair is generated. This means that a valid refresh token can be used ONLY once and cannot be replayed.
    • Issue of refresh token for grant_type=REFRESH_TOKEN ( To enable, set system property GrantTypeRefreshTokenEnabled=true wherein default is false)
    • Auto revoke of used refresh token for grant_type=REFRESH_TOKEN (To enable, set system property -Doauth.auto.revoke.enabled=true wherein default is false)
  • To verify if the access token has been revoked, use http://<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token/info REST API.
    Sample Request
    http://<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token/info
    
    curl --location --request POST '<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token/info' \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --header 'x-oauth-identity-domain-name: DemoDomain' \
    --header 'Cookie: JSESSIONID=VKgaCGYiIiQ_3-gTdIOymIqW4uMXGt2OPNglGjTvJUaVyP4gkNY3!-472705583' \
    --data-urlencode 'access_token=token=eyJraWQiOiJEZW1vRG9tYWluIiwieDV0IjoiZG1HQi1zR1BlcHEzblE2ZWdyRnNkM3c4ZU9
    JIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwOi8vc2xjMDdoYWYudXMub3JhY2xlLmNvbToyMjIyL29hdXRoMiIsImF1
    ZCI6WyJEZW1vUmVzU2VydmVyIiwiYWIwIl0sImV4cCI6MTYxNTM1NTAwOSwianRpIjoiZVEtVHA1N3JUTHFUTktPaERybEpnd
    yIsImlhdCI6MTYxNTM1MTQwOSwic3ViIjoidXNlckEiLCJjdXN0b21BdHRyaXNlc3Npb25JZCI6IjgxOWY5ODc0NDdjMGE1Mzg
    3Mzk1Mjg5OWYzZjUzMTYzMmUxZjRlODI5ZTNmN2FmMjg2OWFhNWY5M2YyMmMyYzMiLCJjdXN0b21BdHRyaTIiOiJSRVNPVVJDR
    UNPTlNUIiwiY2xpZW50IjoiRGVtb0NsaWVudElkIiwic2NvcGUiOlsiRGVtb1Jlc1NlcnZlci5EZWZhdWx0U2NvcGUiXSwiZG9
    tYWluIjoiRGVtb0RvbWFpbiIsInJ0X2lkIjoiM2FmN2Q5NzEtYjAyZS00ZDI5LThlOTMtNWJhMTkzMGJkN2Y2LjE2MTUzNTEzN
    jciLCJncmFudCI6IkFVVEhPUklaQVRJT05fQ09ERSJ9.HBtENqB6nIAUAlcft84o5_tSFiXP_E-tD7Ux6WyC_nO0D1m2x6l7sc
    9oQO8ad1vgXV4KjSGSPnxL09pWLUPDxhwQqs15w_Py1q-SWQxrcpKqtCv-vdz_zCS3_uMsaOLQTQwYyj94tnS9TEWAkQtknDrV
    4vOFhhDMVOOBPIo5h7BeDa9liSIhPjlB7wPAHJ2HX4rOhL5z2BfPS2v9QNUDuJbvKZl78BwHP80L8uDaSsh5a0XMcJGr1PQ9cd0
    6bSWGTF3o9NBLWBiWnPTyq17XDxnr4rEcPrp3bV_iwuIvo0id91iu52L-NTAts0FzTv7gEz2d6lNMwgMAfBFQPWFYRQ'
    Sample Response
    {
        "error": "invalid_grant",
        "error_description": "Access Token Validation Failed"
    }

39.12.2 Revoking OAuth Tokens for a User, Client and Resource Server

In addition to the Runtime API for revoking tokens by OAuth clients, OAM also provides an Administrator API to support revoking all 3-legged OAuth tokens for a specific user, or a specific user-client-resource server combination.

Use the http://<AdminServerHost>:<AdminServerPort>/oam/services/rest/consent/revoke REST API to revoke all the OAuth tokens for a specific user, or a specific user-client-resource server combination.

  • OAM supports token revocation of only those access and refresh tokens that are generated through 3-legged OAuth flow (Authorization code flow).

    For tokens generated through 2-legged OAuth flow, there is no user consent and the client has all the information required to regenerate the tokens. If the client is compromised, it is recommended to delete the client.

  • Consent Management must be enabled for the OAuth tokens to be revoked. If it is not enabled, OAM returns an empty consent:
    []

    For details about how to enable consent management, see Enabling Consent Management

    For details about how to enable consent management in an MDC setup, see Enabling Consent Management on MDC

  • In an MDC setup, the time taken for the token revocation to propagate to all the clone data centers in an MDC setup is dependent on the value set in pollInterval. Recommended value is 5 seconds. That is, if the client revokes the OAuth tokens on the Master data center, it takes at least five seconds for the changes to get propagated to the Clone data centers in the MDC topology. For details about changing pollInterval, see Modifying the Polling Interval in Clone Data Centers

    Also, it is recommended to set the BatchSize to 300. For details, see Table 19-2

    In an MDC setup, this Administrator REST API must be run on the Master node.

Ensure the following headers are added to the request:
  • Authorization : Base64 URL encoded <Administrator>:<Secret> combination.
  • X-OAUTH-IDENTITY-DOMAIN-NAME: Identity Domain name.
  • Content-Type: application/x-www-form-urlencoded: Add the following parameters as key-value pairs in the request body, as required.

Note:

From 12.2.1.4.5 onwards, identity domain can be provided as query parameter identityDomain instead of the header paremeter X-OAUTH-IDENTITY-DOMAIN-NAME.

For more information about the parameters, response codes, error codes, and so on, see Revoke Token REST Endpoints REST API documentation.

Examples

Example 39-1 Revoking All the OAuth Tokens for a User

Specify the userId whose tokens needs to be revoked.

Sample Request
curl --location --request POST '<AdminServerHost>:<AdminServerPort>/oam/services/rest/consent/revoke' \
--header 'Authorization: Basic d2VibG9naWM6d2VsY29tZTE=' \
--header 'x-oauth-identity-domain-name: DemoDomain' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Cookie: JSESSIONID=yIwmL5y29hILQ44F1-yt0t78Lgw0OYNVY1Z_gaz4cqW8xS01ekuE!-1307751471' \
--data-urlencode 'userId=UserA'
Sample Response
{
    "consents": [
        {
            "clientId": "DemoClientId",
            "consentId": "30650989-8e53-3010-b06a-98b0ef42b65d",
            "createTimeStamp": "Fri Mar 12 03:24:08 PST 2021",
            "resourceId": "66ac1a16-ee37-4525-81f6-9062d69a743c",
            "scopes": [
                "DemoResServer.DefaultScope"
            ],
            "tokenRevokeTimestamp": "TOKENS=2021-03-12T03:30:31-0800",
            "valid": true
        }
    ]
}

Example 39-2 Revoking All Refresh Tokens for a Client

Specify the userId, revoke_type, clientIdentifier, and resServerId to revoke all ACCESS_TOKENS for the specified client.

Sample Request
curl --location --request POST '<AdminServerHost>:<AdminServerPort>/oam/services/rest/consent/revoke' \
--header 'Authorization: Basic d2VibG9naWM6d2VsY29tZTE=' \
--header 'x-oauth-identity-domain-name: DemoDomain' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Cookie: JSESSIONID=yIwmL5y29hILQ44F1-yt0t78Lgw0OYNVY1Z_gaz4cqW8xS01ekuE!-1307751471' \
--data-urlencode 'userId=UserA' \
--data-urlencode 'revoke_type=REFRESH_TOKENS' \
--data-urlencode 'clientIdentifier=DemoClientId' \
--data-urlencode 'resServerId=66ac1a16-ee37-4525-81f6-9062d69a743c'
Sample Response
{
    "consents": [
        {
            "clientId": "DemoClientId",
            "consentId": "30650989-8e53-3010-b06a-98b0ef42b65d",
            "createTimeStamp": "Fri Mar 12 03:55:31 PST 2021",
            "resourceId": "66ac1a16-ee37-4525-81f6-9062d69a743c",
            "scopes": [
                "DemoResServer.DefaultScope"
            ],
            "tokenRevokeTimestamp": "REFRESH_TOKENS=2021-03-12T03:56:49-0800",
            "valid": true
        }
    ]
}

Example 39-3 Revoking Refresh Tokens for a User Based on Timestamp

Use the timestamp parameter to revoke refresh tokens generated before the specified timestamp.

Specify the timestamp in the following format: [yyyy]-[MM]-[dd]'T'[HH]:[mm]:[ss]Z, where
  • Z is the time offset from UTC in the format +/-HHmm and denotes +0000 numerically. For example, the UTC offset for New York on standard time can be specified as -0500.
  • yyyy is the year
  • MM is the month
  • dd is the day
  • HH is hour
  • mm is minutes
  • ss is seconds

The following sample request revokes all the tokens for UserA that were generated before the timestamp 2021-03-09T15:30:33+0800

Sample Request
curl --location --request POST '<AdminServerHost>:<AdminServerPort>/oam/services/rest/consent/revoke' \
--header 'Authorization: Basic d2VibG9naWM6d2VsY29tZTE=' \
--header 'x-oauth-identity-domain-name: DemoDomain' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Cookie: JSESSIONID=NysahaoNLyc13HzjEh93gJmwbY4HnMetJQY33RE8_ZdBpzpw7kdr!-472705583' \
--data-urlencode 'userId=UserA' \
--data-urlencode 'revoke_type=REFRESH_TOKENS' \
--data-urlencode 'timestamp=2021-03-09T15:30:33+0800'
Sample Response
{
    "consents": [
        {
            "clientId": "DemoClientId",
            "consentId": "30650989-8e53-3010-b06a-98b0ef42b65d",
            "createTimeStamp": "Tue Mar 09 21:12:06 PST 2021",
            "resourceId": "66ac1a16-ee37-4525-81f6-9062d69a743c",
            "scopes": [
                "DemoResServer.DefaultScope"
            ],
            "tokenRevokeTimestamp": "REFRESH_TOKENS=2021-03-08T23:30:33-0800",
            "valid": true
        }
    ]
}

39.13 Configuring Client Authentication

OAM Bundle Patch 12.2.1.4.210920 and Later Releases. This content applies only to OAM Bundle Patch 12.2.1.4.210920 and later releases.

OAM supports the following client authentication methods:
  • client_secret_basic: uses password for authentication.
  • private_key_jwt: OAM generates JWT tokens for authentication.
  • tls_client_auth: mTLS client authentication.
  • self_signed_tls_client_auth: self-signed mTLS client authentication.
See the following sections for details about Client authentications:

39.13.1 Configuring Identity Domain for Client Authentication

You can add the properties in the body of the https://<admin-host>:<admin-port>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/oauthidentitydomain REST API while creating the Identity Domain. Use the PUT method to update the existing Identity Domain with the properties.

Note:

See the Identity Domain REST Endpoints documentation for details about the properties.
For example,
{
    "tokenEndpointAuthMethodsSupported": [
        "tls_client_auth",
        "self_signed_tls_client_auth",
        "private_key_jwt",
        "client_secret_basic"
    ],
    "issueTLSClientCertificateBoundAccessTokens":"true",
    "tlsClientAuthSubjectDN":"CN=%CLIENT_ID_PLACEHOLDER%, OU=OAM, O=Oracle, L=BLR, ST=KA, C=IN"
}

Note:

  • Do not replace %CLIENT_ID_PLACEHOLDER% with the client id while creating or modifying the identity domain. OAM Server replaces the %CLIENT_ID_PLACEHOLDER% during authentication.
  • You must disable client certificate propagation from OHS to WLS if you intend to use the client_secret _basic authentication method. This is due to the fact that if a client certificate is present, mTLS validation will occur automatically.
  • mTLS will be enforced if the client certificate is sent in the request, regardless of whether it is part of the tokenEndpointAuthMethodsSupported list. Therefore, if OAM needs to ignore client certificates, then you must configure OHS/LBR so that the certificates do not pass to the OAM server.
Identity Domain can include various type of clients, therefore, multiple authentication methods can be configured in the identity domain. The following is the order of precedence of the authentication methods:
  1. mTLS authentication methods: tls_client_auth and self_signed_tls_client_auth
  2. JWT Key authentication method: private_key_jwt
  3. Client Secret authentication method: client_secret_basic

Note:

If the client includes configuration for any of the authentication methods then only that authentication method is used.

39.13.2 Configuring the Client for Client Authentication

You can add the properties in the body of the https://<admin-host>:<admin-port>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/client REST API while creating the client. Use the PUT method to update the existing client with the properties.

Note:

See Client REST Endpoints documentation for details about the properties.
For example,
{
    "tokenEndpointAuthMethod":"tls_client_auth",
    "issueTLSClientCertificateBoundAccessTokens":"true",
    "tlsClientAuthSubjectDN":"C=IN, ST=KA, L=BLR, O=Oracle, OU=OAM, CN=client2, EMAILADDRESS=client2@oracle.com"
}

Note:

Ensure that the tlsClientAuthSubjectDN values match the values in the client certificate.

Authentication method is optional in client configuration. If the authentication method is not provided in the client then the domain level configuration is used. For details, see rfc6749

39.13.3 Managing Client Certificates

In case of CONFIDENTIAL_CLIENT (this is set using the parameter clientType while creating the client. For details, see REST API documentation), only the CA and intermediate CA certificates must be added to the OAM truststore.

For a PUBLIC_CLIENT or a self-signed client certificate, the client certificate must also be included with the client. Use the https://<admin-host>:<admin-port>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/clientartifacts REST API to add the client certificates to the client.

For example:
curl --location --request POST 'https://<admin-host>:<admin-port>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/clientartifacts' \
--header 'Accept: application/json' \
--header 'Authorization: Basic dGVzdDp0ZXN0=' \
--header 'Content-Type: application/json' \
--data '{
    "certificateValue": "<CLIENT_CERTIFICATE>",
    "clientName": "MTLSClient",
    "identityDomainName": "MTLSDomain"
}'

Note:

Certificate that has the issuer matching the subject is treated as self-signed certificate.

39.14 Configuring mTLS Client Authentication

39.14.1 About Mutual Transport Layer Security (mTLS) in OAM

In TLS authentication, the server confirms its identity by producing a certificate (public key), which is then verified by the TLS verification process.

In mTLS (mutual-TLS), along with the server, the client's identity is also verified. The TLS handshake is utilized to validate the client's possession of the private key corresponding to the public key in the certificate and to validate the corresponding certificate chain.

OAM supports configuration to validate the certificate chain at the server and configurations that support termination of SSL at load balancer or proxy end. Load balancer of proxy end points, where SSL is terminated, need not validate the certificate chain as OAM server does the validation.

About Certificate Binding

Certificate binding can be enabled with or without mTLS authentication in OAM. This enables mutual TLS during protected resource access to serve as a proof-of-possession mechanism.

TLS Client certificate binding is not mandatory. Binding is done based on the issueTLSClientCertificateBoundAccessTokens configuration set in the Identity Domain and the Clients.

To configure certificate binding, you can set issueTLSClientCertificateBoundAccessTokens as true or false while creating or modifying the Identity Domain or Clients.

The certificate bound access token contains cnf (confirmation) entry, which contains the thumbprint of the client certificate to which the access token is bound.

You can use the introspect endpoint to validate the certificate binding.

Note:

The cnf entry is present only in the response of the introspect endpoint with certificate bound access token and is not present in access token that is not bound to a certificate.

39.14.2 Configuring mTLS Endpoint

Prerequisite: Ensure you have performed the following procedures before configuring the mTLS endpoint:
To configure the mTLS endpoint, set the hostname and port for the mTLS endpoint using the https://<admin-host>:<admin-port>/oam/services/rest/ssa/api/v1/hostalias/mtls REST API.

Note:

The hostname and port of the mTLS endpoint must match the endpoint, at which SSL gets terminated. For example, if SSL terminates at the loadbalancer then the hostname and port of the mTLS endpoint must match the hostname and port of the loadbalancer.
curl --location --request POST 'https://<admin-host>:<admin-port>/oam/services/rest/ssa/api/v1/hostalias/mtls' \
--header 'Authorization: Basic dGVzdDp0ZXN0=' \
--header 'Content-Type: application/json' \
--data '{
    "hostname": "<HOST_NAME>",
    "port": "4443"
}'

After setting up the mTLS configuration, you can also view the details using the discovery endpoint (.well-known URL, for example: http://<HOST_NAME>:7777/.well-known/openid-configuration).

The response includes the new parameter mtls_endpoint_aliases
"mtls_endpoint_aliases": {
    "token_endpoint": "https://<MTLS_HOST>:<MTLS_PORT>/oauth2/rest/token",
    "revocation_endpoint": "https://<MTLS_HOST>:<MTLS_PORT>/oauth2/rest/token/revoke",
    "introspection_endpoint": "https://<MTLS_HOST>:<MTLS_PORT>/oauth2/rest/token/introspect"
},

Also see, Configuring OpenIDConnect Discovery Endpoint

39.14.3 Managing Trust Certificates for mTLS

Clients must provide certificates for mTLS authentication. The certificates can be signed from a known Certificate Authority (CA), self-signed, or from a custom CA. In case of certificate chaining, the client must include the certificate chain.

Trusted CA certificates must be added to the OAM truststore. Use the https://<admin-host>:<admin-port>/oam/services/rest/ssa/api/v1/security/trust/oauthClient/certificate REST API to manage trusted CA certificates.

Use the POST method of the https://<admin-host>:<admin-port>/oam/services/rest/ssa/api/v1/security/trust/oauthClient/certificate REST API to add certificates to the OAM trustore. For example:
curl --location --request PUT 'https://<admin-host>:<admin-port>/oam/services/rest/ssa/api/v1/security/trust/oauthClient/certificate' \
--header 'Authorization: Basic dGVzdDp0ZXN0=' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data-raw '{
    "id": "testCACert",
    "publicCert": "MIICrTCCAhYCBAuHHScwDQYJKoZIhvcNAQELBQAwgZsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlDdXBlcnRpbm8xFDASBgNVBAoTC09ibGl4LCBJbmMuMREwDwYDVQQLEwhOZXRQb2ludDE6MDgGA1UEAxMxTmV0UG9pbnQgU2ltcGxlIFNlY3VyaXR5IENBIC0gTm90IGZvciBHZW5lcmFsIFVzZTAeFw0xNzA0MTEwODEwNTZaFw0yNzA0MDkwODEwNTZaMBsxGTAXBgNVBAMMEGRlZmF1bHRfb2FtX2NlcnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGlNx2IWPZpNsPqCNmR3J/tE750TNhFRtFQ4Xbj72CU2R65Cu+PxwPQQkIP29h2mRjBfZk8hjlH0lcLEz3a6/RQcTXe/EXicEuVz0WMtlusUDO9Em6JYuUMrEy58jPVhEBtJ8iv3S9t7dJc8b3THsADpxARGjSAJHI/zKidn1WssBm+3BA1cIMUMpjUCpl4R5pRJUwHCvSF3G6fE+GXIVZh64ygD5kTuM36GOAyDQ7o6zRIeugNkQ3OJGVLNlhGcwoSvhn8YyBzKzW128J9g+Lj3KNxhM4+MGkrebgI3Ez4ZMw4MhxbpzgrW0KjHq7uKXJFP8EQsCKjZbR/hwxiG6PAgMBAAEwDQYJKoZIhvcNAQELBQADgYEAJYi5tZ9X6gBrvHzZ4wEsXHEuNYnL9MYDUyF6P7nkwMfThns1yyHByoE7WPQd7ans4WBX/HToZfz1xLh50QFqpKDS4C6mD/M9fffSuSHOvR4mVug8cWghORmwc1SSuLLzxXl+LFmnGLwJNtP1ffPCfZqPRrd0lPcO/ifGPz50zfU="
}

See Client Trust Certificates REST Endpoints documentation for details.

For OCSP client certificate validation, perform the following steps:
  1. Add the OCSP Server certificate into OAM trustore. For example
    curl --location --request PUT 'https://<admin-host>:<admin-port>/oam/services/rest/ssa/api/v1/security/trust/oauthClient/certificate' \
    --header 'Authorization: Basic dGVzdDp0ZXN0=' \
    --header 'Content-Type: application/json' \
    --header 'Accept: application/json' \
    --data-raw '{
        "id": "OCSPServerCert",
        "publicCert": "MIICrTCCAhYCBAuHHScwDQYJKoZIhvcNAQELBQAwgZsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlDdXBlcnRpbm8xFDASBgNVBAoTC09ibGl4LCBJbmMuMREwDwYDVQQLEwhOZXRQb2ludDE6MDgGA1UEAxMxTmV0UG9pbnQgU2ltcGxlIFNlY3VyaXR5IENBIC0gTm90IGZvciBHZW5lcmFsIFVzZTAeFw0xNzA0MTEwODEwNTZaFw0yNzA0MDkwODEwNTZaMBsxGTAXBgNVBAMMEGRlZmF1bHRfb2FtX2NlcnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGlNx2IWPZpNsPqCNmR3J/tE750TNhFRtFQ4Xbj72CU2R65Cu+PxwPQQkIP29h2mRjBfZk8hjlH0lcLEz3a6/RQcTXe/EXicEuVz0WMtlusUDO9Em6JYuUMrEy58jPVhEBtJ8iv3S9t7dJc8b3THsADpxARGjSAJHI/zKidn1WssBm+3BA1cIMUMpjUCpl4R5pRJUwHCvSF3G6fE+GXIVZh64ygD5kTuM36GOAyDQ7o6zRIeugNkQ3OJGVLNlhGcwoSvhn8YyBzKzW128J9g+Lj3KNxhM4+MGkrebgI3Ez4ZMw4MhxbpzgrW0KjHq7uKXJFP8EQsCKjZbR/hwxiG6PAgMBAAEwDQYJKoZIhvcNAQELBQADgYEAJYi5tZ9X6gBrvHzZ4wEsXHEuNYnL9MYDUyF6P7nkwMfThns1yyHByoE7WPQd7ans4WBX/HToZfz1xLh50QFqpKDS4C6mD/M9fffSuSHOvR4mVug8cWghORmwc1SSuLLzxXl+LFmnGLwJNtP1ffPCfZqPRrd0lPcO/ifGPz50zfU="
    }
  2. Enable OCSP certificate validation. For details, see Enabling OCSP Certificate Validation

39.14.4 Configuring Additional Options to Support mTLS

Perform the additional configurations to support mTLS authentication

  • Set the WebLogic Plug-In Enabled to Yes.
    1. Login to the WebLogic Console and navigate to the server instance (for example, oam_server1, and Advanced)
    2. Check the Client Cert Proxy Enabled checkbox
    3. Set the WebLogic Plug-In Enabled option to Yes
  • If SSL terminates at OHS, perform the following changes in the ohs ssl.conf file under MIDDLEWARE_HOME/user_projects/domains/base_domain/config/fmwconfig/components/OHS/instances/ohs1:
    • In the SSL Wallet, search for “${ORACLE_INSTANCE}“ and in the next line, add SSLOptions, StdEnvVars, and ExportCertData.
    • Change SSLVerifyClient none to SSLVerifyClient require
  • Configure the load balancer to support mTLS configuration. Configure 2 way SSL endpoint in load balancer and import CA and intermediate CA of client certificate to the load balancer of the trust store. For details, see Configuring SSL for the Web Tier
  • To provide support for custom cert headers, add the parameter "enableHeaderCertValue":true under CustomAttrs in the Identity Domain REST API. For example:
    "customAttrs":"{"domainCertValidityInDays":"30", "consentExpiryTimeInMinutes":"10","enableHeaderCertValue":true}"

    Once enabled, the headers must be provided under the following two http headers:

    • SSL_CLIENT_CERT: Client certificate.
    • SSL_CLIENT_ROOT_CERT: Root CA or intermediate CA certificates

    Note:

    This is applicable only for load balancers other than OHS terminating the SSL connection

39.14.5 Sample 2-Legged mTLS Authentication Flow

The following example provides a sample 2-legged mTLS authentication flow:

  1. Create the Identity Domain
    curl --location --request POST 'https://<admin-host>:<admin-port>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/oauthidentitydomain' \
    --header 'Authorization: Basic dGVzdDp0ZXN0=' \
    --header 'Content-Type: application/json' \
    --data '{
        "name": "MTLSDomain",
        "identityProvider": "UserIdentityStore1",
        "description": "MTLSDomain",
        "tokenSettings": [
            {
                "tokenType": "ACCESS_TOKEN",
                "tokenExpiry": 3600,
                "lifeCycleEnabled": false,
                "refreshTokenEnabled": false,
                "refreshTokenExpiry": 86400,
                "refreshTokenLifeCycleEnabled": false
            },
            {
                "tokenType": "AUTHZ_CODE",
                "tokenExpiry": 3600,
                "lifeCycleEnabled": false,
                "refreshTokenEnabled": false,
                "refreshTokenExpiry": 86400,
                "refreshTokenLifeCycleEnabled": false
            },
            {
                "tokenType": "SSO_LINK_TOKEN",
                "tokenExpiry": 3600,
                "lifeCycleEnabled": false,
                "refreshTokenEnabled": false,
                "refreshTokenExpiry": 86400,
                "refreshTokenLifeCycleEnabled": false
            }
        ],
        "errorPageURL": "/oam/pages/error.jsp",
        "consentPageURL": "/oam/pages/consent.jsp",
        "customAttrs": "{\"domainCertValidityInDays\":\"30\", \"consentExpiryTimeInMinutes\":\"10\"}",
        "tokenEndpointAuthMethodsSupported": [
            "tls_client_auth",
            "self_signed_tls_client_auth"
        ],
        "issueTLSClientCertificateBoundAccessTokens":"true",
        "tlsClientAuthSubjectDN":"CN=%CLIENT_ID_PLACEHOLDER%, OU=OAM, O=Oracle, L=BLR, ST=KA, C=IN"
    }'
  2. Create the Resource
    curl --location --request POST 'https: //<admin-host>:<admin-port>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/application' \
    --header 'Content-Type: application/json' \
    --header 'Authorization: Basic dGVzdDp0ZXN0=' \
    --data '{
        "name": "MTLSResource",
        "description": "Oracle Cloud",
        "scopes": [
            {
                "scopeName": "viewRes",
                "description": "View  registered resources"
            },
            {
                "scopeName": "editRes",
                "description": "Edit  registered resources"
            },
            {
                "scopeName": "delRes",
                "description": "Delete  registered resources"
            }
        ],
        "tokenAttributes": [
            {
                "attrName": "sessionId",
                "attrValue": "$session.id",
                "attrType": "DYNAMIC"
            },
            {
                "attrName": "resSrvAttr",
                "attrValue": "RESOURCECONST",
                "attrType": "STATIC"
            }
        ],
        "idDomain": "MTLSDomain",
        "audienceClaim": {
            "subjects": [
                "user"
            ]
        }
    }'
  3. Create the Client:
    curl --location --request POST 'https://<admin-host>:<admin-port>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/client' \
    --header 'Content-Type: application/json' \
    --header 'Authorization: Basic dGVzdDp0ZXN0=' \
    --data '{
        "attributes": [
            {
                "attrName": "staticAttr",
                "attrValue": "CustomValue",
                "attrType": "static"
            }
        ],
        "secret": "welcome1",
        "id": "MTLSClient",
        "scopes": [
            "MTLSResource.viewRes",
            "MTLSResource.editRes",
            "MTLSResource.delRes"
        ],
        "clientType": "CONFIDENTIAL_CLIENT",
        "idDomain": "MTLSDomain",
        "description": "OAuth Client Description",
        "name": "MTLSClient",
        "grantTypes": [
            "PASSWORD",
            "CLIENT_CREDENTIALS",
            "JWT_BEARER",
            "REFRESH_TOKEN",
            "AUTHORIZATION_CODE",
            "IMPLICIT"
        ],
        "defaultScope": "MTLSResource.viewRes",
        "redirectURIs": [
            {
                "url": "{redirect_URL}",
                "isHttps": false
            }
        ],
        "tokenEndpointAuthMethod":"tls_client_auth",
        "issueTLSClientCertificateBoundAccessTokens":"true",
        "tlsClientAuthSubjectDN":"C=IN, ST=KA, L=BLR, O=Oracle, OU=OAM, CN=client2, EMAILADDRESS=client2@oracle.com"
    }'
  4. Add the CA certificate to the OAM truststore:
    curl --location --request POST 'https://<admin-host>:<admin-port>/oam/services/rest/ssa/api/v1/security/trust/oauthClient/certificate?certID=MTLSClient' \
    --header 'Accept: application/json' \
    --header 'Authorization: Basic dGVzdDp0ZXN0=' \
    --header 'Content-Type: application/json' \ 
    --data '{
        "publicCert": "<CA_CERT>",
        "id": "MTLSClient"
    }'
  5. The 2-legged flow using mTLS endpoint starts here:
    curl -k --key <PATH_TO_CLIENT_KEY> --cert <PATH_TO_CLIENT_CERTIFICATE> --location --request POST 'https://<mTLS_HOST>:<mTLS_PORT>/oauth2/rest/token' \
    --header 'X-OAUTH-IDENTITY-DOMAIN-NAME: MTLSDomain' \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --data-urlencode 'grant_type=PASSWORD' \
    --data-urlencode 'redirect_uri=<REDIRECT_URI>' \
    --data-urlencode 'username=weblogic' \
    --data-urlencode 'password=<PASSWORD>' \
    --data-urlencode 'client_id=MTLSClient'
  6. Run the introspect REST API to get details from the token.
    curl --key <PATH_TO_CLIENT_KEY> --cert <PATH_TO_CLIENT_CERTIFICATE> --location --request POST 'https://<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token/introspect' \
    --header 'X-OAUTH-IDENTITY-DOMAIN-NAME: MTLSDomain' \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --data-urlencode 'token=<ACCESS_TOKEN>
    Following is the sample response received:
    {
        "iss": "http://<HOST_NAME>:7777",
        "aud": [
            "MTLSResource",
            "http://<HOST_NAME>:7777"
        ],
        "exp": 1629898603,
        "jti": "gv4Ms01THuOWAE27d3lMLQ",
        "iat": 1629895003,
        "sub": "weblogic",
        "client": "MTLSClient",
        "scope": [
            "MTLSResource.viewRes"
        ],
        "domain": "MTLSDomain",
        "staticAttr": "CustomValue",
        "cnf": {
            "x5t#S256": "yxa_pacafklt_5mqjjc_shtb9qhbvdx0pzght3a5nxc"
        },
        "rem_exp": 3409,
        "active": true
    }

39.14.6 Sample 3-Legged mTLS Authentication Flow

The following example provides a sample 3-legged mTLS authentication flow:

  1. Create the Identity Domain
    curl --location --request POST 'https://<admin-host>:<admin-port>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/oauthidentitydomain' \
    --header 'Authorization: Basic dGVzdDp0ZXN0=' \
    --header 'Content-Type: application/json' \
    --data '{
        "name": "MTLSDomain",
        "identityProvider": "UserIdentityStore1",
        "description": "MTLSDomain",
        "tokenSettings": [
            {
                "tokenType": "ACCESS_TOKEN",
                "tokenExpiry": 3600,
                "lifeCycleEnabled": false,
                "refreshTokenEnabled": false,
                "refreshTokenExpiry": 86400,
                "refreshTokenLifeCycleEnabled": false
            },
            {
                "tokenType": "AUTHZ_CODE",
                "tokenExpiry": 3600,
                "lifeCycleEnabled": false,
                "refreshTokenEnabled": false,
                "refreshTokenExpiry": 86400,
                "refreshTokenLifeCycleEnabled": false
            },
            {
                "tokenType": "SSO_LINK_TOKEN",
                "tokenExpiry": 3600,
                "lifeCycleEnabled": false,
                "refreshTokenEnabled": false,
                "refreshTokenExpiry": 86400,
                "refreshTokenLifeCycleEnabled": false
            }
        ],
        "errorPageURL": "/oam/pages/error.jsp",
        "consentPageURL": "/oam/pages/consent.jsp",
        "customAttrs": "{\"domainCertValidityInDays\":\"30\", \"consentExpiryTimeInMinutes\":\"10\"}",
        "tokenEndpointAuthMethodsSupported": [
            "tls_client_auth",
            "self_signed_tls_client_auth"
        ],
        "issueTLSClientCertificateBoundAccessTokens":"true",
        "tlsClientAuthSubjectDN":"CN=%CLIENT_ID_PLACEHOLDER%, OU=OAM, O=Oracle, L=BLR, ST=KA, C=IN"
    }'
  2. Create the Resource
    curl --location --request POST 'https: //<admin-host>:<admin-port>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/application' \
    --header 'Content-Type: application/json' \
    --header 'Authorization: Basic dGVzdDp0ZXN0=' \
    --data '{
        "name": "MTLSResource",
        "description": "Oracle Cloud",
        "scopes": [
            {
                "scopeName": "viewRes",
                "description": "View  registered resources"
            },
            {
                "scopeName": "editRes",
                "description": "Edit  registered resources"
            },
            {
                "scopeName": "delRes",
                "description": "Delete  registered resources"
            }
        ],
        "tokenAttributes": [
            {
                "attrName": "sessionId",
                "attrValue": "$session.id",
                "attrType": "DYNAMIC"
            },
            {
                "attrName": "resSrvAttr",
                "attrValue": "RESOURCECONST",
                "attrType": "STATIC"
            }
        ],
        "idDomain": "MTLSDomain",
        "audienceClaim": {
            "subjects": [
                "user"
            ]
        }
    }'
  3. Create the Client
    curl --location --request POST 'https://<admin-host>:<admin-port>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/client' \
    --header 'Content-Type: application/json' \
    --header 'Authorization: Basic dGVzdDp0ZXN0=' \
    --data '{
        "attributes": [
            {
                "attrName": "staticAttr",
                "attrValue": "CustomValue",
                "attrType": "static"
            }
        ],
        "secret": "welcome1",
        "id": "MTLSClient",
        "scopes": [
            "MTLSResource.viewRes",
            "MTLSResource.editRes",
            "MTLSResource.delRes"
        ],
        "clientType": "CONFIDENTIAL_CLIENT",
        "idDomain": "MTLSDomain",
        "description": "OAuth Client Description",
        "name": "MTLSClient",
        "grantTypes": [
            "PASSWORD",
            "CLIENT_CREDENTIALS",
            "JWT_BEARER",
            "REFRESH_TOKEN",
            "AUTHORIZATION_CODE",
            "IMPLICIT"
        ],
        "defaultScope": "MTLSResource.viewRes",
        "redirectURIs": [
            {
                "url": "{redirect_URL}",
                "isHttps": false
            }
        ],
        "tokenEndpointAuthMethod":"tls_client_auth",
        "issueTLSClientCertificateBoundAccessTokens":"true",
        "tlsClientAuthSubjectDN":"C=IN, ST=KA, L=BLR, O=Oracle, OU=OAM, CN=client2, EMAILADDRESS=client2@oracle.com"
    }'
  4. Add the CA certificate to the OAM truststore
    curl --location --request POST 'https://<admin-host>:<admin-port>/oam/services/rest/ssa/api/v1/security/trust/oauthClient/certificate?certID=MTLSClient' \
    --header 'Accept: application/json' \
    --header 'Authorization: Basic dGVzdDp0ZXN0=' \
    --header 'Content-Type: application/json' \
     
    --data '{
        "publicCert": "<CA_CERT>",
        "id": "MTLSClient"
    }'
  5. The 3-legged flow starts here:
    Open a browser, and run the following from the browser:
    https://<OHS_Host>:<OHS_Port>/oauth2/rest/authorize?response_type=code&domain=MTLSDomain&client_id=MTLSClient&scope=MTLSResource.viewRes%20openid&state=code1234&redirect_uri=<redirect_URL>&nonce=""
    

    Login using your user name and password credentials. In the next Consent page, click Allow to get the authentication code from the page URL.

  6. Use the authentication code from the previous step to fetch the access token
    curl --key <PATH_TO_CLIENT_KEY> --cert <PATH_TO_CLIENT_CERTIFICATE> --location --request POST 'https://<mTLS_HOST>:<mTLS_PORT>/oauth2/rest/token' \
    --header 'X-OAUTH-IDENTITY-DOMAIN-NAME: MTLSDomain' \
    --header 'Authorization: Basic dGVzdDp0ZXN0=' \
    --data-urlencode 'grant_type=AUTHORIZATION_CODE' \
    --data-urlencode 'code=<CODE>' \
    --data-urlencode 'redirect_uri=<redirect_URL>' \
    --data-urlencode 'client_id=MTLSClient'
    
  7. Run the introspect REST API to get details from the token.
    curl --key <PATH_TO_CLIENT_KEY> --cert <PATH_TO_CLIENT_CERTIFICATE> --location --request POST 'https://<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token/introspect' \
    --header 'X-OAUTH-IDENTITY-DOMAIN-NAME: MTLSDomain' \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --data-urlencode 'token=<ACCESS_TOKEN>'
    Following is the sample response received:
    {
        "iss": "http://<HOST_NAME>:7777",
        "aud": [
            "MTLSResource",
            "MTLSClient",
            "http://<HOST_NAME>:7777",
        ],
        "exp": 1629894002,
        "jti": "cuWu5Mzae9Hn00cBUErzKw",
        "iat": 1629890402,
        "sub": "weblogic",
        "client": "MTLSClient",
        "scope": [
            "MTLSResource.viewRes",
            "openid"
        ],
        "domain": "MTLSDomain",
        "grant": "AUTHORIZATION_CODE",
        "sessionId": "5e63e6ba-7eca-43fa-b264-52f4e26aecbd=",
        "staticAttr": "CustomValue",
        "nonce": "%22%22",
        "resSrvAttr": "RESOURCECONST",
        "cnf": {
            "x5t#S256": "yxa_pacafklt_5mqjjc_shtb9qhbvdx0pzght3a5nxc"
        },
        "rem_exp": 3523,
        "active": true
    }

39.15 Proof Key for Code Exchange (PKCE) Support in OAM

This section provides details about the Proof Key for Code Exchange (PKCE) enhancement.

In OAuth 2.0, 3-legged flow, public clients that use the authorization_code, client_id, and client_secret parameters for requesting access token from the authorization server are vulnerable to interception attacks. Once the attacker gains access to the authorization code and the client_secret, it can also retrieve the access token, therefore compromising the entire security of the 3-legged flow.

To prevent this, OAM provides Proof Key for Code Exchange (PKCE) support for OAuth 2.0 authorization code grant flow.

In a typical PKCE flow, the clients use a temporary one-time dynamic credential called code_verifier instead of the static client_secret. A SHA256 hashed string is generated from the code_verifier called the code_challenge, which is then used to request the Authorization Code. The access token is then requested from the authorization server by sending the authorization code along with the code_verifier in the request. The authorization server (OAM) hashes the code_verifier and compares it with the previously received code_challenge. Only if these two values match, the access token is issued, thereby enhancing the security of the authorization code grant flow.

Note:

OAM validates code_challenge for Base64 with padding. To fix this and ensure RFC compliant behavior for the code_challenge (Base64 without padding as described in https://tools.ietf.org/html/rfc7636#appendix-A), you must download and apply the OAM Patch 32406872. For details, see the note How To Enable OAuth Proof Key For Code Exchange (PKCE) in Oracle Access Manager (OAM) 12.2.1.4 (Doc ID 2755209.1) at https://support.oracle.com.

OAM will support only the RFC compliant behavior in all the subsequent releases.

See the following sections for more details about enabling PKCE and generating access token through PKCE flow.

39.15.1 Enabling PKCE

If you need enhanced security with the 3-legged OAuth 2.0 code grant flow, you can enable PKCE by setting UsePKCE either at the domain or client level.

  • The UsePKCE values are case-sensitive.
  • The domain level values are applicable to all the clients under that specific domain. If you need to apply PKCE for a specific client, you can enable PKCE by setting the UsePKCE parameter only for that client.
  • The client level values take precedence over the domain level values.

Enabling PKCE at Domain Level

At domain level, you can enable PKCE by adding UsePKCE in customAttrs and setting it to one of the following values:
Values Behavior and Description
ALL_CLIENTS_TYPES

PKCE is enabled for all client types.

If the PKCE parameters code_verifier and code_challenge are not provided in the authorization_code and token_access request, the authorization flow switches to the non-PKCE 3-legged OAuth flow and completes.

ALL_CLIENTS_TYPES_STRICT

PKCE is enabled for all client types.

If the PKCE parameters code_verifier and code_challenge are not provided in the authorization_code and token_access request, the authorization fails.

PUBLIC_CLIENTS

PKCE is enabled for PUBLIC_CLIENTS only.

If the PKCE parameters code_verifier and code_challenge are not provided in the authorization_code and token_access request, the authorization flow switches to the non-PKCE 3-legged OAuth flow and completes.

For non-public clients, that PKCE parameters are ignored if used.

PUBLIC_CLIENTS_STRICT

PKCE is enabled for PUBLIC_CLIENTS only.

If the PKCE parameters code_verifier and code_challenge are not provided in the authorization_code and token_access request, the authorization fails.

The following example shows a sample request to enable PKCE when creating the domain. To update an existing domain with PKCE parameters use the PUT method.

See Identity Domain REST Endpoints for the REST API documentation.

curl --request POST '<AdminServer>:<AdminPort>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/oauthidentitydomain' \
--header 'Authorization: Basic d2VibG9naWM6d2VibG9naWMx' \
--header 'Content-Type: application/json' \
--header 'Cookie: JSESSIONID=OweshB5ejqWvx6wDrFbHD1sc67WsGbEWu4sBp3aeZ3Ki7kLPLEY7!1934427792' \
--data-raw '{
    "name": "DemoDomain",
    "identityProvider": "UserIdentityStore1",
    "description": "Test Domain",
    "tokenSettings": [
        {
            "tokenType": "ACCESS_TOKEN",
            "tokenExpiry": 3600,
            "lifeCycleEnabled": false,
            "refreshTokenEnabled": false,
            "refreshTokenExpiry": 86400,
            "refreshTokenLifeCycleEnabled": false
        },
        {
            "tokenType": "AUTHZ_CODE",
            "tokenExpiry": 3600,
            "lifeCycleEnabled": false,
            "refreshTokenEnabled": false,
            "refreshTokenExpiry": 86400,
            "refreshTokenLifeCycleEnabled": false
        },
        {
            "tokenType": "SSO_LINK_TOKEN",
            "tokenExpiry": 3600,
            "lifeCycleEnabled": false,
            "refreshTokenEnabled": false,
            "refreshTokenExpiry": 86400,
            "refreshTokenLifeCycleEnabled": false
        }
    ],
    "errorPageURL": "/oam/pages/servererror.jsp",
    "consentPageURL": "/oam/pages/consent.jsp",
    "customAttrs": "{\"usePKCE\":\"ALL_CLIENTS_TYPES\"}"
}'

Enabling PKCE at Client Level

At client level, you can enable PKCE by setting the UsePKCE parameter to one of the following values:
Values Behavior and Desciption
STRICT

If the PKCE parameters code_verifier and code_challenge are not provided in the authorization_code and token_access request, the authorization fails.

NON_STRICT

If the PKCE parameters code_verifier and code_challenge are not provided in the authorization_code and token_access request, the authorization flow switches to the non-PKCE 3-legged OAuth flow and completes.

The following example shows a sample request to enable PKCE when creating the client. To update an existing client with the PKCE parameters use the PUT method.

See Client REST Endpoints for the REST API documentation.

curl --request POST '<AdminServer>:<AdminPort>/oam/services/rest/ssa/api/v1/oauthpolicyadmin/client' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic d2VibG9naWM6d2VibG9naWMx' \
--header 'Cookie: JSESSIONID=OweshB5ejqWvx6wDrFbHD1sc67WsGbEWu4sBp3aeZ3Ki7kLPLEY7!1934427792' \
--data-raw '{
    "attributes": [
        {
            "attrName": "customeAttr1",
            "attrValue": "CustomValue",
            "attrType": "static"
        }
    ],
    "secret": "<client_secret>",
    "id": "DemoClientId",
    "scopes": [
        "DemoResServer.scope1"
    ],
    "clientType": "PUBLIC_CLIENT",
    "idDomain": "DemoDomain",
    "description": "Client Description",
    "name": "DemoClient",
    "grantTypes": [
        "PASSWORD",
        "CLIENT_CREDENTIALS",
        "JWT_BEARER",
        "REFRESH_TOKEN",
        "AUTHORIZATION_CODE"
    ],
    "defaultScope": "DemoResServer.scope1",
    "usePKCE": "NON_STRICT",
    "redirectURIs": [
        {
            "url": "http://localhost:8080/Sample.jsp",
            "isHttps": true
        }
    ]
}'

39.15.2 PKCE Flow for Access Token Generation

This section provides the PKCE flow details for Access Token generation.

  1. Create or update your Identity Domain by adding UsePKCE in customAttrs. For details, see Enabling PKCE at Domain Level
  2. If the resource server already exists, skip this step. If not, add a resource server as described in the section Creating a Resource.
  3. Create or update the OAuth Client by adding the UsePKCE parameter. For details, see Enabling PKCE at Client Level
  4. If the OAuth 3-legged flow is already setup, skip this step. If not, perform the manual side steps on OAM server and WebGate as described in the section 3 - Legged Flows — process under Runtime REST APIs for OAuth 12c
  5. Generate a cryptographically random key called code_verifier.

    code_verifier refers to a cryptographically random URL safe string generated using the characters A-Z, a-z, 0-9, and the punctuation characters -._~ (hyphen, period, underscore, and tilde). The string must be between 43 and 128 characters long.

    Note:

    A unique code_verifier must be created for each authorization request.

    For example, Y1lgBSx8gRsruplrdpGiG-9Lkv~kna1q2pgwXY7UYKc~~jTgMkmUlZkZkapJGT6X.m12.ZUBDj24qWuPGHl21x3vyFEC.m_XDH_JTw4Qk6_a62Qw~e0sVp3I-AHYhTzn

    This code_verifier will be used to request the Access Token later.

  6. Generate code_challenge string from the code_verifier.

    code_challenge refers to the transformed BASE64-URL-encoded string of the SHA256 hash of the code_verifier.

    For example, for code_verifier: Y1lgBSx8gRsruplrdpGiG-9Lkv~kna1q2pgwXY7UYKc~~jTgMkmUlZkZkapJGT6X.m12.ZUBDj24qWuPGHl21x3vyFEC.m_XDH_JTw4Qk6_a62Qw~e0sVp3I-AHYhTzn, the transformed SHA256 hashed string, code_challenge, is Ec-YfJRRibqf_myiWqObZfT-M1HthBUTygBH73zEHbc.

  7. Through the browser, request the Authorization Code. Send the code_challenge along with code_challenge_method in the authorization_code request to the authorization server (OAM).
    code_challenge_method value can be one of the following:
    • Plain: Sets the code_verifier as code_challenge instead of the hashed value.
    • S256 (Recommended): Indicates the hashed value of the code_verifier is set as code_challenge.

    Note:

    A unique Authorization Code can be exchanged for a single Access Token only. Authorization Code replay is rejected by OAM server.

    Authorization Code Sample Request

    http://<OHS Hostname>:<OHS Port>/oauth2/rest/authz?response_type=code
    &client_id=TestClient&domain=TestDomain&scope=TestResourceServer.scope1&state=xyz
    &redirect_uri=http://localhost:8080/Sample.jsp
    &code_challenge=Ec-YfJRRibqf_myiWqObZfT-M1HthBUTygBH73zEHbc
    &code_challenge_method=S256

    Authorization Code Sample Response

     http://localhost:8080/Sample.jsp?code=UlF6aVY3eFVIemNTVWhVcWlmM0o1UT09fkJ5b0J4MlRVdFhwVFYySXhKR1RUS1NnOWV4UE1oUGRKMFYxR3RmbGt
    FYjJYK3lMUUxDRGxyZXNHa2VrRXRtQVp1S25MYVY1YXVkbFFGNmx5MUtCcXFZYWJhRlhpRENIcjI0Vm1YZjNtRE1hTzFDL1lmbEhKK0wvK2pBeUdTZWNYbEMza2dBSnM0Q0ZrZ1R
    NNmQ3SUVuSmZJNExScEI4ZUJySVpMT1hEZ1p5alp5eHVxSkd2RllCdVFqcFpEQTJEaCt5Z1JxN21ZWFQyc3JKQi9EY0JrTDhiUVBlb0laNkFzdVhJL1JURjBpWFVvK2VPelVxaVo
    zSjBMMjJncmZlcEhxMzh1N0hkZ0pqaEZZZmgyRWJHakkxMnlBeE9nVlRxRXdxcXhaazdCdW5mQ3VORFkvVHBLUXRvNEJpUzlEby9vcXlXaEJnZ08vMjExbE5NSFhHUVJFTHkrTlp
    4aGNWUzBVMFd2cFVJcWpUd3ZHVjBEZmlaOVBQbWI5b3FhT3gvUFpXdVdrYjczRDJBeUw4RVJjdjMyQ2NnTEZRMXV0aDE2enVOYm9aYVNVb1pjOTJsRGliTGJxRWYrOTZtbXlVNll
    SNkxRWEVqd2ovTVBpaHc2TzRrbFZXMysrM2kyaGxuYmhoNFdOeENSL1NvLysrTDBXQktUQVhrb2Y0NzF6WTY1VXhIcFg0bG56REoxcURjTFFlSnNMUUE1aVNtMWtocDlzYW1CRFd
    0YWRpcEhsT1JzK0hydDk4K0pFb0ZaSDYwaWJ1QlZMZGc0dzJ2ekh2ZWpLWU1ldnBIUWdjRVlBeDVVaENmOVg4dloyb0hhV0J6ekMyMExCQTdTdnFudyt1ZVV6Nkp3cWZON1N6VGJ0
    UnA3UGk2U1JablVBK0k1bTduR1haOWwzVklQeHRKWWIwNHVObXY5NkFxN2tUMEMwb0djb2FlK1c0NGFTekFvKzd1bFdFbnFuZz09&state=xyz
  8. Request the access token from the authorization server (OAM) using the authorization_code and the code_verifier.

    Access Token Sample Request

    
    curl  --request POST 'http://<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token' \
    --header 'X-OAUTH-IDENTITY-DOMAIN-NAME: DemoDomain' \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --header 'Cookie: JSESSIONID=OweshB5ejqWvx6wDrFbHD1sc67WsGbEWu4sBp3aeZ3Ki7kLPLEY7!1934427792' \
    --data-urlencode 'grant_type=AUTHORIZATION_CODE' \
    --data-urlencode 'code=UlF6aVY3eFVIemNTVWhVcWlmM0o1UT09fkJ5b0J4MlRVdFhwVFYySXhKR1RUS1NnOWV4UE1oUGRKMFYxR3RmbGt
    FYjJYK3lMUUxDRGxyZXNHa2VrRXRtQVp1S25MYVY1YXVkbFFGNmx5MUtCcXFZYWJhRlhpRENIcjI0Vm1YZjNtRE1hTzFDL1lmbEhKK0wvK2pBe
    UdTZWNYbEMza2dBSnM0Q0ZrZ1RNNmQ3SUVuSmZJNExScEI4ZUJySVpMT1hEZ1p5alp5eHVxSkd2RllCdVFqcFpEQTJEaCt5Z1JxN21ZWFQyc3J
    KQi9EY0JrTDhiUVBlb0laNkFzdVhJL1JURjBpWFVvK2VPelVxaVozSjBMMjJncmZlcEhxMzh1N0hkZ0pqaEZZZmgyRWJHakkxMnlBeE9nVlRxR
    XdxcXhaazdCdW5mQ3VORFkvVHBLUXRvNEJpUzlEby9vcXlXaEJnZ08vMjExbE5NSFhHUVJFTHkrTlp4aGNWUzBVMFd2cFVJcWpUd3ZHVjBEZml
    aOVBQbWI5b3FhT3gvUFpXdVdrYjczRDJBeUw4RVJjdjMyQ2NnTEZRMXV0aDE2enVOYm9aYVNVb1pjOTJsRGliTGJxRWYrOTZtbXlVNllSNkxRW
    EVqd2ovTVBpaHc2TzRrbFZXMysrM2kyaGxuYmhoNFdOeENSL1NvLysrTDBXQktUQVhrb2Y0NzF6WTY1VXhIcFg0bG56REoxcURjTFFlSnNMUUE1
    aVNtMWtocDlzYW1CRFd0YWRpcEhsT1JzK0hydDk4K0pFb0ZaSDYwaWJ1QlZMZGc0dzJ2ekh2ZWpLWU1ldnBIUWdjRVlBeDVVaENmOVg4dloyb0h
    hV0J6ekMyMExCQTdTdnFudyt1ZVV6Nkp3cWZON1N6VGJ0UnA3UGk2U1JablVBK0k1bTduR1haOWwzVklQeHRKWWIwNHVObXY5NkFxN2tUMEMwb0
    djb2FlK1c0NGFTekFvKzd1bFdFbnFuZz09' \
    --data-urlencode 'redirect_uri=http://localhost:8080/Sample.jsp' \
    --data-urlencode 'code_verifier=Y1lgBSx8gRsruplrdpGiG-9Lkv~kna1q2pgwXY7UYKc~~jTgMkmUlZkZkapJGT6X.m12.ZUBDj24qWuPGHl21x3vyFEC.m_XDH_JTw4Qk6_a62Qw~e0sVp3I-AHYhTzn' \
    --data-urlencode 'client_id=DemoClientId'

    Access Token Sample Response

    {"access_token":"eyJraWQiOiJEZW1vRG9tYWluIiwieDV0IjoieGVmZExvZnpienRnTkJ2NGR3QXFnYkJyZGhvIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwOi8vc2xjMTZmc3UudXMub3JhY2
    xlLmNvbToxNzI5OC9vYXV0aDIiLCJhdWQiOlsiRGVtb1Jlc1NlcnZlciIsImFiMCJdLCJleHAiOjE2MDQ5OTM0ODcsImp0aSI6InFPV0ZKYk1tdldmTW5IalA4Z0hVamciLCJpYXQiOjE2MDQ5ODk4ODcsInN1YiI6In
    dlYmxvZ2ljIiwiY3VzdG9tZUF0dHIxIjoiQ3VzdG9tVmFsdWUiLCJjb2RlX2NoYWxsZW5nZV9tZXRob2QiOiJTMjU2Iiwic2Vzc2lvbklkIjoiOTEyNTA2NWItZDJiNC00YWE1LTliNTctZjllZTU3NDUzZjQyfDJraS
    9iWnRHYkYyT3FXOWhDRkJHcFpkcjJDTjZaTnJJWGszMFNURUV1N1k9IiwiY29kZV9jaGFsbGVuZ2UiOiJFYy1ZZkpSUmlicWZfbXlpV3FPYlpmVC1NMUh0aEJVVHlnQkg3M3pFSGJjPSIsInJlc1NydkF0dHIiOiJSRV
    NPVVJDRUNPTlNUIiwiY2xpZW50IjoiRGVtb0NsaWVudElkIiwic2NvcGUiOlsiRGVtb1Jlc1NlcnZlci5zY29wZTEiXSwiZG9tYWluIjoiRGVtb0RvbWFpbiJ9.cpR4L9UhIF4ZyPyelKgUeHzVQlIiqIN0vaqqPmC8a
    ed19JQFRzpI4xL8jlU4cFXFd9bwSX3_Y6s5Y16eMtSQ1DnOX-u-eoFYE4O6G8AitOAG2oWy82R1O5YJ693Aa7ovVf2VZ8Y1y-JG17HBK4TBXqUgOLhVgURtLsPCJ_Knjyut_TC44NbxsVfRAuOo2li-3vSeCrAi776bM
    6TXLPo9VeYJvhGmVQyFA6Fe4QZ5qSLrU2r8Oi7p0plCjTQgEIt2EoHjH88-nfbZ35F4K3zha3UOh4l1gAtkq0HgkP2okwIcMNPk7t0p6kXMWNNm9tDAWCCOKN_Fhyv2_c7JqRZSrQ",
    "token_type":"Bearer","expires_in":3600}

    Note:

    OAM hashes the code_verifier and compares it with the previously received code_challenge. Only if these two values match, the access token is issued.
  9. Validate the Access Token.

    Validate Access Token Sample Request

    curl --location --request GET 'http://<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token/info?access_token=<AccessToken> \
    --header 'X-OAUTH-IDENTITY-DOMAIN-NAME: DemoDomain' \
    --header 'Cookie: JSESSIONID=d4SxI2e58dgP6XbZepQo8uPRequ1cynWMjKtQyymVQhbi424TIOl!1934427792'

39.16 Token Exchange Support in OAM

This section provides details about the token exchange support in OAM.

Token Exchange provides a mechanism to an OAuth client to exchange a token for impersonation or delegation use cases. For more information, see RFC 8693.

39.16.1 Enabling Token Exchange Support

To enable token exchange support several identity domain custom attributes,resource server token attributes and client grant_type TOKEN_EXCHANGE must be used.

The Identity domain custom attributes to be used are:
Name Description Default

TokenExchange_DelegationEnabled, TokenExchange_ImpersonationEnabled

set to true to enable delegation/impersonation

false

TokenExchange_TokenExpiryInSeconds

Expiry of issued_token

Expiry is set to tokenExpiry value for ACCESS_TOKEN (Existing setting)

TokenExchange_DelegationClaimsToBeCopied, TokenExchange_ImpersonationClaimsToBeCopied

',' separated value to indicate the list of claims to be copied from subject_token to issued_token. For example, mygroups,name

null (No claims apart from sub is copied from subject_token)

TokenExchange_EnforceMayActClaim

If may_act claim is present in the subject_token, sub claim from may_act claim will be matched with sub claim from actor_token.

Set to false to disable the check.

true

TokenExchange_OAMIssuers

',' separated list to indicate the list of issuers to be considered as OAM issuers. Consents are evaluated for OAM tokens only. By default, tokens are considered to be issued by OAM instance if the issuer field matches the OAM server LBR configured. If the issuer is different, this property can be used. If the property is set to ALL_ISSUERS, all tokens are considered as issued by the same OAM instance. This is a ',' separated property. Can be needed in MDC environments with consent management enabled.

None
The resource server token attributes to be used are:
Name Description Default

TokenExchange_AllowedClientsForDelegation, TokenExchange_AllowedClientsForImpersonation

',' separated value to indicate the list of clientids allowed for creating an issued_token with the resource server scopes

null(No client isallowed)

Note:

The scopes expected in the issued token must be assigned to the client.
Client must have the following grant_type:
Name Value Default
grant_type TOKEN_EXCHANGE Null
Following are the request and response parameters to be used to generate exchange token.

Table 39-8 Request Parameters

Name Requirement Support type/values
grant_type REQUIRED TOKEN_EXCHANGE or urn:ietf:params:oauth:grant-type:token-exchange
resource OPTIONAL if scope parameter is provided present. Else, REQUIRED. ResourceServerName configured in OAM. Multiple parameters can be specified as defined at https://datatracker.ietf.org/doc/html/draft-ietf-oauth-resource-indicators-08
audience OPTIONAL Any string. Multiple parameters can be specified as defined at https://datatracker.ietf.org/doc/html/draft-ietf-oauth-resource-indicators-08
scope OPTIONAL if resource parameter is provided. Else, REQUIRED Space-separated scope values.
requested_token_type OPTIONAL urn:ietf:params:oauth:token-type:jwt
subject_token REQUIRED JWS token
subject_token_type REQUIRED urn:ietf:params:oauth:token-type:jwt
actor_token OPTIONAL JWS token
actor_token_type OPTIONAL, REQUIRED only if actor_token is passed urn:ietf:params:oauth:token-type:jwt

Table 39-9 Response Parameters

Name Supported type/values
access_token JWS token
issued_token_type urn:ietf:params:oauth:token-type:jwt
token_type Bearer
expires_in Validity in seconds
scope space separated scopes

CURL Commands

Following are a few example CURL commands to create or modify the identity domain, target resource server, OAuth Client, delegation request, and impersonation request.
  1. Create identity domain with TokenExchange attributes
    curl --location --request POST 'http://oamadminhost:oamadminport/oam/services/rest/ssa/api/v1/oauthpolicyadmin/oauthidentitydomain' \
    --header 'Authorization: Basic YWRtaW46cGFzc3dvcmQ=' \
    --header 'Content-Type: application/json' \
    --data '{                                                   \
        "name": "CompanyDomain",                             \
        "identityProvider": "oid",                           \
        "description": "Updated Domain",                        \
        "tokenSettings": [                                      \
            {                                                   \
                "tokenType": "ACCESS_TOKEN",                    \
                "tokenExpiry": 3600,                            \
                "lifeCycleEnabled": false,                      \
                "refreshTokenEnabled": true,                    \
                "refreshTokenExpiry": 86400,                    \
                "refreshTokenLifeCycleEnabled": false           \
            },                                                  \
            {                                                   \
                "tokenType": "AUTHZ_CODE",                      \
                "tokenExpiry": 3600,                            \
                "lifeCycleEnabled": false,                      \
                "refreshTokenEnabled": true,                    \
                "refreshTokenExpiry": 86400,                    \
                "refreshTokenLifeCycleEnabled": false           \
            }                                                   \
        ],                                                      \
        "errorPageURL": "/oam/pages/servererror.jsp",           \
        "consentPageURL": "/oam/pages/consent.jsp",             \
        "keyPairRolloverDurationInHours": "24",                 \
        "customAttrs": "{\"TokenExchange_DelegationEnabled\":\"true\",\"TokenExchange_DelegationClaimsToBeCopied\":\"mygroups\" ,\"TokenExchange_TokenExpiryInSeconds\":\"300\"  }" \
    }'
  2. Create a target resource server with clientid allowed for delegation (Re-create a resource server if an update to an existing client id is needed)
    curl --location --request POST 'http://oamadminhost:oamadminport/oam/services/rest/ssa/api/v1/oauthpolicyadmin/application' \
    --header 'Content-Type: application/json' \
    --header 'Authorization: Basic YWRtaW46cGFzc3dvcmQ=' \
    --data '{                                                           \
        "name": "PublishService_ResourceServer",                        \
        "description": "Resource server for publish service",           \
        "scopes": [                                                     \
            {                                                           \
                "scopeName": "publish",                                 \
                "description": "Publish the user profile"               \
            },                                                          \
            {                                                           \
                "scopeName": "backup",                                  \
                "description": "Backup the user profile"                \
            }                                                           \
        ],                                                              \
        "tokenAttributes": [                                            \
            {                                                           \
            "attrName": "TokenExchange_AllowedClientsForDelegation",    \
            "attrValue": "PublishServiceClientId",                      \
            "attrType": "static"                                        \
        }                                                               \
        ],                                                              \
        "idDomain": "CompanyDomain",                                    \
        "audienceClaim": {                                              \
            "subjects": [                                               \
                "http://abc.publishservice.com"                         \
            ]                                                           \
        } }'
  3. Create a OAuth Client with TOKEN_EXCHANGE grant type
    curl --location --request POST 'http://oamadminhost:oamadminport/oam/services/rest/ssa/api/v1/oauthpolicyadmin/client' \
    --header 'Content-Type: application/json' \
    --header 'Authorization: Basic YWRtaW46cGFzc3dvcmQ=' \
    --data '{                                                           \
        "attributes": [                                                 \
                                                                   \
        ],                                                              \
        "secret": "password",                                           \
        "id": "PublishServiceClientId",                                    \
        "scopes": [                                                     \
           "PublishService_ResourceServer.publish"                 \
        ],                                                              \
        "clientType": "CONFIDENTIAL_CLIENT",                            \
        "idDomain": "CompanyDomain",                                    \
        "description": "Publish service client",                           \
        "name": "PublishServiceClientName",                                \
        "grantTypes": [                                                 \
            "CLIENT_CREDENTIALS",                                            \
            "TOKEN_EXCHANGE"                                        \
        ],                                                              \
        "defaultScope": "PublishService_ResourceServer.publish",   \
        "redirectURIs": [                                               \
            {                                                           \
                "url": "https://oauthdebugger.com/debug",               \
                "isHttps": true                                         \
            }                                                           \
        ]                                                               \
    }
  4. The TOKEN_EXCHANGE endpoint is:
    http://<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token/exchange
  5. Delegation request
    curl --location --request POST 'http://<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token/exchange' \
    --header 'X-OAUTH-IDENTITY-DOMAIN-NAME: CompanyDomain' \
    --header 'Authorization: Basic UHVibGlzaFNlcnZpY2VDbGllbnRJZDp3ZWxjb21lMQ==' \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --header 'charset: UTF-8' \
    --data-urlencode 'grant_type=TOKEN_EXCHANGE' \
    --data-urlencode 'subject_token=eyJraWQiOiJDb21wYW55RG9tYWluIiwieDV0IjoiSUliLTdDcnBxaDBGY1VseDVNekJZLWVXUTFVIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwOi8vYWJiaGF0b2QtaWRtc2UucmVnMi5zdXNlbmdkZXYxcGh4Lm9yYWNsZXZjbi5jb206MTQxMDAvb2F1dGgyIiwiYXVkIjpbImh0dHA6Ly9hYmJoYXRvZC1pZG1zZS5yZWcyLnN1c2VuZ2RldjFwaHgub3JhY2xldmNuLmNvbToxNDEwMC9vYXV0aDIiLCJodHRwOi8vYWJjLlVzZXJQcm9maWxlQXBwbGljYXRpb24uY29tIiwiVXNlclByb2ZpbGVBcHBsaWNhdGlvbl9SZXNvdXJjZVNlcnZlciJdLCJleHAiOjE2NzU2NjY2MjgsImp0aSI6IjJudWRVS01ZdUttbGZJUnRyNHF2TFEiLCJpYXQiOjE2NzU2NjMwMjgsInN1YiI6ImF3c3VzcjEiLCJjbGllbnQiOiJVc2VyUHJvZmlsZUNsaWVudElkIiwic2NvcGUiOlsiVXNlclByb2ZpbGVBcHBsaWNhdGlvbl9SZXNvdXJjZVNlcnZlci5yZWFkIiwiVXNlclByb2ZpbGVBcHBsaWNhdGlvbl9SZXNvdXJjZVNlcnZlci51cGRhdGUiXSwiZG9tYWluIjoiQ29tcGFueURvbWFpbiIsImdyYW50IjoiQVVUSE9SSVpBVElPTl9DT0RFIiwibXlncm91cHMiOiJvcmcxMDpvcmcxMjpvcmcxMTpvcmcxNDpvcmcxMzpvcmcxNjpvcmcxNTpvcmcxODpvcmcxNzpvcmcxOTpvcmc4Om9yZzk6b3JnNDpvcmc1Om9yZzY6b3JnNzpvcmcyMTpvcmcyMDpvcmcyMzpvcmcyMjpvcmcyNTpvcmcyNDphd3NncnAyOm9yZzE6b3JnMjphd3NncnAxOm9yZzMifQ.fV9aW9a1aocYdRvxZN_XX2AGfEuHz6aCnsc84wmV0dmq7MJhDHYY0u7Oa7_yKjgN2ZNPAp_atSYDf3yo48gdDS4-6OUgqUeXLgyrJyo0-eNBG1QEkQfZXm_lRdAWGaeAk0c5Wzk6Yj2NHmMBEFQ8cHx8tysz-CW21C42dy24g0rwgSek_9GXj7NLf2smZZge9asIogCGDQPIUsPdTFuGmrc0NX7u82kMfl2bZIdn1pBy9216tRRnlAOLuoE025uhZSury36ArYDGKumI4PXv5I07RBFC5VbrxfgnvCaM1zkwcBgCb_ei8BM7vz9TgOycKBhEg7-AiSChVbY2s8ldEA' \
    --data-urlencode 'subject_token_type=urn:ietf:params:oauth:token-type:jwt \
    ' \
    --data-urlencode 'actor_token=eyJraWQiOiJDb21wYW55RG9tYWluIiwieDV0IjoiSUliLTdDcnBxaDBGY1VseDVNekJZLWVXUTFVIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwOi8vYWJiaGF0b2QtaWRtc2UucmVnMi5zdXNlbmdkZXYxcGh4Lm9yYWNsZXZjbi5jb206MTQxMDAvb2F1dGgyIiwiYXVkIjpbImh0dHA6Ly9hYmJoYXRvZC1pZG1zZS5yZWcyLnN1c2VuZ2RldjFwaHgub3JhY2xldmNuLmNvbToxNDEwMC9vYXV0aDIiLCJQdWJsaXNoU2VydmljZV9SZXNvdXJjZVNlcnZlciIsImh0dHA6Ly9hYmMucHVibGlzaHNlcnZpY2UuY29tIl0sImV4cCI6MTY3NTY2MzQyOSwianRpIjoiZll5VV9CcUNyeE9zdm5LRXpJdUNVQSIsImlhdCI6MTY3NTY1OTgyOSwic3ViIjoiUHVibGlzaFNlcnZpY2VDbGllbnRJZCIsImNsaWVudCI6IlB1Ymxpc2hTZXJ2aWNlQ2xpZW50SWQiLCJzY29wZSI6WyJQdWJsaXNoU2VydmljZV9SZXNvdXJjZVNlcnZlci5wdWJsaXNoIl0sImRvbWFpbiI6IkNvbXBhbnlEb21haW4ifQ.bCxSCclNKizykDtRZU2-CEseCCE8b9kFFJseq-xeKYxoaF3-V5hZgR5NND70zZsMHvArreAq37-ZtnWSm_rkOSb0TWxf7nfjdKhTAmKKIvyF0J1kfLwrF40cLfgdppmZQhXIyZuU1btxGO0d_ozheIv7yU60VR9Yyk5ukc4KdfFVDBAympu35s00nZG4kZ-uh4f5rm_R94fajS3aJaZvA_d7v-axisKnwgGthBWjhwa1IPJcgtS31pGSjQfsxShl9Or67aFQ1ZbTi9uHPm8ehUot9FKbrYhmcVzaj_M0pld4Scoqoc6_eZ4iaU3Jf4RiO_Jr-BLd5t6dfcdzbCUi-Q' \
    --data-urlencode 'actor_token_type=urn:ietf:params:oauth:token-type:jwt \
    ' \
    --data-urlencode 'scope=PublishService_ResourceServer.publish'
  6. Impersonation request
    curl --location --request POST 'http://<ManagedServerHost>:<ManagedServerPort>/oauth2/rest/token/exchange' \
    --header 'X-OAUTH-IDENTITY-DOMAIN-NAME: CompanyDomain' \
    --header 'Authorization: Basic UHVibGlzaFNlcnZpY2VDbGllbnRJZDp3ZWxjb21lMQ==' \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --header 'charset: UTF-8' \
    --data-urlencode 'grant_type=TOKEN_EXCHANGE' \
    --data-urlencode 'subject_token=eyJraWQiOiJDb21wYW55RG9tYWluIiwieDV0IjoiSUliLTdDcnBxaDBGY1VseDVNekJZLWVXUTFVIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwOi8vYWJiaGF0b2QtaWRtc2UucmVnMi5zdXNlbmdkZXYxcGh4Lm9yYWNsZXZjbi5jb206MTQxMDAvb2F1dGgyIiwiYXVkIjpbImh0dHA6Ly9hYmJoYXRvZC1pZG1zZS5yZWcyLnN1c2VuZ2RldjFwaHgub3JhY2xldmNuLmNvbToxNDEwMC9vYXV0aDIiLCJodHRwOi8vYWJjLlVzZXJQcm9maWxlQXBwbGljYXRpb24uY29tIiwiVXNlclByb2ZpbGVBcHBsaWNhdGlvbl9SZXNvdXJjZVNlcnZlciJdLCJleHAiOjE2NzU2NzAwOTksImp0aSI6IkFTM21pZktON0VBSHRzOUEtRjBBV0EiLCJpYXQiOjE2NzU2NjY0OTksInN1YiI6ImF3c3VzcjEiLCJjbGllbnQiOiJVc2VyUHJvZmlsZUNsaWVudElkIiwic2NvcGUiOlsiVXNlclByb2ZpbGVBcHBsaWNhdGlvbl9SZXNvdXJjZVNlcnZlci5yZWFkIiwiVXNlclByb2ZpbGVBcHBsaWNhdGlvbl9SZXNvdXJjZVNlcnZlci51cGRhdGUiXSwiZG9tYWluIjoiQ29tcGFueURvbWFpbiIsImdyYW50IjoiQVVUSE9SSVpBVElPTl9DT0RFIiwibXlncm91cHMiOiJvcmcxMDpvcmcxMjpvcmcxMTpvcmcxNDpvcmcxMzpvcmcxNjpvcmcxNTpvcmcxODpvcmcxNzpvcmcxOTpvcmc4Om9yZzk6b3JnNDpvcmc1Om9yZzY6b3JnNzpvcmcyMTpvcmcyMDpvcmcyMzpvcmcyMjpvcmcyNTpvcmcyNDphd3NncnAyOm9yZzE6b3JnMjphd3NncnAxOm9yZzMifQ.XNckHvnkRlblkkcuxWloNcahJ2eP2Yxv3LP6dJi9XlvIkR55Dm7H_LKOSouK2zogoIJBgryB9cNZ5M0MAS6DymQ-Nj8UxZAChgrJ7vIzMCHLFwizefIBYkE7LtYWqR2O0aeXnkqFkPgJ2bVpC3hut-7iGiMMlSERpMgJ15cYUGn3Dww6K-5uWMjoS06eFStdABcpW94wvdNEHkRGgR4rTLHjpuFttRkyU190e6BA0O2GbfmC7kbFX6q8ooC0pw6CmwpuM2ggmVcT7pF1Kyx_pkpYebFo5njqBS5ir9r18t-k4XHbQDvft-gtq0898vMw7t1WjO8otolaASwypjH8qg' \
    --data-urlencode 'subject_token_type=urn:ietf:params:oauth:token-type:jwt \
    ' \
    --data-urlencode 'scope=PublishService_ResourceServer.publish'

39.17 Custom Issuer Support

The issuer in tokens (access_token/id_token) can be customized now.  By specifying OmitIssuerPort, the user can mask/omit the port from the issuer, while CustomIssuerPathExtension can specify a custom extension for the path replacing the oauth2 details.

Following are the steps to configure these parameters.
  1. Check if OAuthConfig exists.
    curl --location 'http://<AdminServerHost>:<AdminServerPort>/iam/admin/config/api/v1/config?path=%2FDeployedComponent%2FServer%2FNGAMServer%2FProfile%2Fssoengine%2FOAuthConfig' \
    --header 'Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=' \

    Response

    1. if OAuthConfig does not exists: 422 Unprocessable Entity (WebDAV) (RFC 4918)
    2. if OAuthConfig exists: 200
      <Configuration xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsd:schemaLocation="http://higgins.eclipse.org/sts/Configuration Configuration.xsd" Path="/DeployedComponent/Server/NGAMServer/Profile/ssoengine/OAuthConfig">
          <Setting Name="OAuthConfig" Type="htf:map">
              <Setting Name="SettingName" Type="xsd:string">settingValue</Setting>
          </Setting>
      </Configuration>
  2. Configure the required parameters.
    1. if OAuthConfig does not exists, then set OAuthConfig to enable userPasswordChangeCheck feature.
      curl --location --request PUT 'http://<AdminServerHost>:<AdminServerPort>/iam/admin/config/api/v1/config?path=%2FDeployedComponent%2FServer%2FNGAMServer%2FProfile%2Fssoengine%2FOAuthConfig' \
      --header 'Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=' \
      --data '<Setting Name="OAuthConfig" Type="htf:map" Path="/DeployedComponent/Server/NGAMServer/Profile/ssoengine/OAuthConfig">
          <Setting Name="CustomIssuerPathExtension" Type="xsd:string">customPath</Setting>
          <Setting Name="OmitIssuerPort" Type="xsd:boolean">true</Setting>
      </Setting>'
    2. if OAuthConfig exists, then append to existing OAuthConfig. Set OAuthConfig for OmitIssuerPort and CustomIssuerPathExtension
      curl --location --request PUT 'http://<AdminServerHost>:<AdminServerPort>/iam/admin/config/api/v1/config?path=%2FDeployedComponent%2FServer%2FNGAMServer%2FProfile%2Fssoengine%2FOAuthConfig' \
      --header 'Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=' \
      --data '<Setting Name="OAuthConfig" Type="htf:map" Path="/DeployedComponent/Server/NGAMServer/Profile/ssoengine/OAuthConfig">
          <Setting Name="SettingName" Type="xsd:string">settingValue</Setting>
          <Setting Name="CustomIssuerPathExtension" Type="xsd:string">customPath</Setting>
          <Setting Name="OmitIssuerPort" Type="xsd:boolean">true</Setting>
      </Setting>'

    Note:

    PUT using /iam/admin/config/api/v1/config replaces the existing configuration with new values, make sure you cross check existing configuration using a GET before updating the configuration using PUT API. For details on:
  3. Once the feature is enabled, it must be reflected in the issuer parameter of the OIDC-configuration.
    Request:
    http://<AdminServerHost>:<AdminServerPort>/.well-known/openid-configuration
    Response will contain the newly configured issuer:
    "issuer": "http://<AdminServerHost>:<AdminServerPort>/customPath"

    You can verify this feature by generating a new access_token/id_token. In the generated access_token/id_token the iss claim should contain the customized issuer value.