swagger: '2.0' info: x-ibm-name: oauth2-oidc-provider title: OAuth2 OIDC Provider version: 1.0.0 description: >- Provide a template on how to enable OIDC for APIC OAuth provider. Authorization Code : the standard OAuth protocol Resource Owner Grant Type : the 2 legged owner grant type Client Credential : there is no user in this, and thus no id_token will be created Skip: Implicit : this is a subset of authorization code grant type, public client contact: url: 'https://www.ibm.com/support/home/product/I433959L64023U66/IBM_API_Connect' name: IBM schemes: - https host: $(catalog.host) basePath: / securityDefinitions: clientID: description: application's client_id in: query name: client_id type: apiKey clientIdHeader: in: header type: apiKey name: X-IBM-Client-Id clientSecretHeader: in: header type: apiKey name: X-IBM-Client-Secret security: - clientID: [] paths: /oauth2/authorize: get: produces: - text/html summary: endpoint for Authorization Code and Implicit grants description: description parameters: - name: response_type in: query description: request an authorization code or or access token (implicit) required: true type: string enum: - code - token - name: scope in: query description: Scope being requested type: string required: true - name: redirect_uri in: query type: string description: URI where user is redirected to after authorization required: false - name: state in: query type: string description: >- This string will be echoed back to application when user is redirected required: false responses: '200': description: An HTML form for authentication or authorization of this request. '302': description: > Redirect to the clients redirect_uri containing one of the following - **authorization code** for Authorization code grant - **access token** for Implicity grant - **error** in case of errors, such as the user has denied the request security: - clientID: [] post: consumes: - application/x-www-form-urlencoded produces: - text/html summary: submit approval to authorization code or access token description: > Submit resource owners approval (or rejection) for the OAuth2 Server to issue an authorization code or access token to the application. security: [] parameters: - name: client_id in: formData description: application requesting the access code or token required: true type: string - name: scope in: formData description: requested scope of this authorization required: true type: string - name: resource-owner in: formData description: resource owners user name required: true type: string - name: redirect_uri in: formData description: >- URI the application is requesting this code or token to be redirected to required: true type: string - name: original-url in: formData description: URL of the original authorization request required: true type: string - name: dp-state in: formData description: state information provided in the authorization form required: true type: string - name: dp-data in: formData description: state information provided in the authorization form required: true type: string responses: '200': description: Cool /oauth2/token: post: consumes: - application/x-www-form-urlencoded produces: - application/json summary: Request Access Tokens description: > This endpoint allows requesting an access token following one of the flows below: - Authorization Code (exchange code for access token) - Client Credentials (2-legged, there isnt resource owner information) - Resource Owner Password Credentials (2-legged, client provides resource owner name and password) - Refresh Token (exchange refresh token for a new access code) The table below indicates the required parameters for each specific grant_type options. Empty cells indicate a parameter is ignored for that specific grant type. Client authentication: - Confidential clients should authenticate using HTTP Basic Authentication. Alternatively, they may post their client_id and client_secret information as a formData parameter. - Public clients should send their client_id as formData parameter. | grant_type | code | client_credentials | password | refresh_token | |----------------------|------------|--------------------|-------------|---------------| | client_id | required* | required* | required* | required* | | client_secret | required* | required* | required* | required* | | code | required | | | | | redirect_uri | required | | | | | username | | | required | | | password | | | required | | | scope | | optional | optional | | | refresh_token | | | | required | The implicit grant requests, see /oauth2/authorize. security: [] parameters: - name: grant_type in: formData description: Type of grant type: string required: true enum: - authorization_code - password - client_credentials - refresh_token - name: client_id in: formData description: >- Application client ID, can be provided in formData or using HTTP Basic Authentication required: false type: string - name: client_secret in: formData description: >- Application secret, must be provided in formData or using HTTP Basic Authentication required: false type: string - name: code in: formData description: Authorization code provided by the /oauth2/authorize endpoint required: false type: string - name: redirect_uri in: formData description: >- required only if the redirect_uri parameter was included in the authorization request /oauth2/authorize; their values MUST be identical. required: false type: string - name: username in: formData type: string description: Resource owner username required: false - name: password in: formData type: string description: Resource owner password required: false - name: scope in: formData type: string description: Scope being requested required: false - name: refresh_token in: formData type: string description: >- The refresh token that the client wants to exchange for a new access token (refresh_token grant_type) required: false responses: '200': description: 'json document containing token, etc.' schema: $ref: '#/definitions/access_token_response' '400': description: json document that may contain additional details about the failure /oauth2/revoke: post: consumes: - application/x-www-form-urlencoded summary: Introspect a given access_token supported description: | This endpoint introspects a given access_token security: - clientIdHeader: [] clientSecretHeader: [] parameters: - name: token in: formData description: 'String value of the access_token, or refresh_token to be revoked' required: true type: string - name: token_type_hint in: formData description: >- This must contain 'access_token' or 'refresh_token' to indicate the token type required: true type: string responses: '200': description: not applicable /oauth2/introspect: post: consumes: - application/x-www-form-urlencoded produces: - application/json summary: Introspect a given access_token supported description: | This endpoint introspects a given access_token security: - clientIdHeader: [] clientSecretHeader: [] parameters: - name: token in: formData description: String value of the access_token to be introspected required: true type: string - name: token_type_hint in: formData description: This must contain 'access_token' to indicate the token type required: true type: string responses: '200': description: 'json document containing issued information, etc.' schema: $ref: '#/definitions/introspect_response' '401': description: failure /oauth2/issued: get: produces: - application/json summary: Returns list of permission granted to the owner description: > This endpoint allows the return of all the issued permission for a given authenticated owner per owner authentication defined in the x-ibm-configuration section security: - clientIdHeader: [] clientSecretHeader: [] responses: '200': description: 'json document containing issued information, etc.' schema: $ref: '#/definitions/issued_responses' '401': description: failure in retreiving issued list delete: consumes: - application/x-www-form-urlencoded produces: - application/json summary: Revoke an application/client permission by the authorized owner description: Revoke an application/client permission by the authorized owner security: - clientIdHeader: [] clientSecretHeader: [] parameters: - name: client-id in: query description: client-id is the OAuth client_id or application id to be revoked required: true type: string responses: '200': description: OK x-ibm-configuration: testable: true enforced: true phase: realized oauth2: client-type: confidential scopes: weather: Weather Information openid: Enable OIDC grants: - password - accessCode - application - implicit identity-extraction: type: basic authentication: x-ibm-authentication-url: url: 'https://$(api.endpoint.address):9443/utility/basic-auth/spoon/spoon' tls-profile: '' authorization: type: authenticated access-token: ttl: 3600 refresh-token: count: 2048 ttl: 2682000 gateway: datapower-gateway assembly: execute: - set-variable: title: set-variable actions: - set: iss.claim value: $(OIDCIssuer) - set: sign-jwk value: $(JWSSignPrivateKey) - set: jwt.sign.algorithm value: $(JWSAlgorithm) - set: oidc.custom.claim value: '{"disclaimer":"For OpenBanking OIDC demo purpose"}' version: 1.0.0 - switch: title: switch case: - condition: >- (((request.verb==='GET')&&(api.operation.path==='/oauth2/authorize'))||((request.verb==='POST')&&(api.operation.path==='/oauth2/authorize')) && new String (apim.getvariable ('message.status.code')).startsWith ('302')) execute: - xslt: title: xslt input: false version: 1.0.0 source: >- - condition: >- ((request.verb==='POST')&&(api.operation.path==='/oauth2/token')) execute: - gatewayscript: title: gatewayscript version: 1.0.0 source: >- let _apimgmt = session.name('_apimgmt'); let grantType = _apimgmt.getVariable('requested-grant-type'); if (grantType === 'password' || grantType === 'code') { // get scope var splitScope = (apim.getvariable('message.body').scope || '').split(' '); if (splitScope.length === 0) { var vScopeNode = session.name('INPUT').getVariable('oauth/verified-scope').item(0).childNodes; if (vScopeNode !== undefined && vScopeNode !== null) { let vScope = vScopeNode.item(0).textContent; splitScope = vScope.split(' '); } } for (let i = 0; i < splitScope.length; i++) { if (splitScope[i] === 'openid') { let userIdentity = _apimgmt.getVariable('authenticated-username'); apim.setvariable('oidc-credential', userIdentity, 'set'); } } } version: 1.0.0 - if: title: if condition: apim.getvariable('oidc-credential') !== undefined execute: - xslt: title: xslt input: false version: 1.0.0 source: >- { "c_hash":" " "at_hash":" " , "s_hash":" " , "s_hash":" " , "nonce":" " , "custom_attribute":" " } - jwt-generate: title: jwt-generate iss-claim: iss.claim exp-claim: 3600 version: 1.0.0 jwt: idtoken jti-claim: true sub-claim: oidc-credential aud-claim: client.app.id private-claims: added.claim jws-alg: RS256 jws-jwk: sign-jwk - gatewayscript: title: gatewayscript version: 1.0.0 source: >- let grantType = session.name('_apimgmt').getVariable('requested-grant-type'); if (grantType === 'implicit') { // regression in 5070 will not allow access, and modification to the location header let location = apim.getvariable('oidc-location') + '&id_token=' + apim.getvariable("idtoken"); // work around is to use xslt apim.setvariable('oidc-location', location); } else { if (apim.getvariable('oidc-location') !== undefined && apim.getvariable('oidc-location').indexOf('code=') !== -1) { let location = apim.getvariable('oidc-location') + '&id_token=' + apim.getvariable("idtoken"); apim.setvariable('oidc-location', location); } else { let token = apim.getvariable("message.body"); token["id_token"] = apim.getvariable("idtoken"); apim.setvariable("message.body", JSON.stringify(token)); } } - if: title: if condition: >- new String (apim.getvariable('message.status.code')).startsWith('302') execute: - xslt: title: xslt input: false version: 1.0.0 source: > version: 1.0.0 version: 1.0.0 catch: [] properties: JWSSignPrivateKey: value: >- { "kty": "RSA", "d": "ZgiybjfeIsoihPMRQpT9Yv5Qfvg5AaqdGRK8mb1G73_CrOjpTbXjs7t0AKKNTGFUlvla4ag9kof4qzA7EB0Kgpsn05668sQtenIkz83pP1v7MaM31YovGq1WCmCpV8lJvuaSAP06ueRmEYG5zhtT9lK3TVxvuYwCd_Ukfe0M3R3ajyLEvPLhnwS5mybAj0mP5lat1l29qXhC-WNhDRZfl6NdVge4yGyKLsNAXqWw0bi3ARE3dYPt7J36cqoET4agwOjjupxY8Ctv1tFw7Xj3lcUBciT_tYi3tKVs8ALalTQ-MHOXHEdDXaAxzgmLVgFD05bbE55OL25MLSvoD0bLAQ", "e": "AQAB", "use": "sig", "kid": "spoon", "alg": "RS256", "n": "iE7cj97VkW-QXXU0U9Fedjl7digjnp_R7lx6LHLugHfS5Xp26GCxOO1pNktSHsfof5EMJ0y8iqtIH4X3QYLg6E6fEZQD4-ZpIaKhTDuel1Zls_NRFgrQ0gzB3oiNJbNMfbNLpx4hCauRRv_RqRb1__jkBRIiU3MrEmB6gBDBQYJ9vwcYDXT5qowAopoZk6p1bf6kftMswVoFsILt9XdBynTHcLPyj61mP0faUb5_VRkpXaCbyCn4G1XakKswqzSkULImNQykaK_I6IJ0CGI0gnnx5YmwNbo4AYS-8fDODXfThDZC12TM_BlCGQMAao2jSSXaebI1nyxmgaYV1oChbw" } description: '' encoded: false OIDCIssuer: value: IBM APIc description: '' encoded: false JWSAlgorithm: value: RS256 description: '' encoded: false definitions: access_token_response: type: object additionalProperties: false required: - token_type - access_token - expires_in properties: token_type: enum: - bearer access_token: type: string expires_in: type: integer scope: type: string refresh_token: type: string introspect_response: type: object additionalProperties: false required: - active - client_id - client_name - username - sub - exp - expstr - iat - nbf - nbfstr - scope properties: active: type: boolean client_id: type: string client_name: type: string username: type: string sub: type: string exp: type: string expstr: type: string iat: type: string nbf: type: string nbfstr: type: string scope: type: string miscinfo: type: string consented_on: type: string consented_on_str: type: string grant_type: type: string issued_response: type: object additionalProperties: false required: - clientId - owner - scope - issuedAt - expiredAt - refreshTokenIssued properties: clientId: type: string clientName: type: string owner: type: string scope: type: string issuedAt: type: string expiredAt: type: string refreshTokenIssued: type: boolean miscInfo: type: string consentedOn: type: string appId: type: string org: type: string orgId: type: string catalog: type: string catalogId: type: string issued_responses: type: array items: $ref: '#/definitions/issued_response' externalDocs: url: >- https://www.ibm.com/support/knowledgecenter/SSMNED_5.0.0/com.ibm.apic.toolkit.doc/tapic_sec_api_config_oidc.html description: Securing your APIs with OpenID Connect