Tutorial: Implementing OIDC Security

This tutorial shows you how to add OIDC (OpenID Connect) capability to an existing native OAuth provider using API Manager.

About this tutorial

OpenID Connect is an authentication protocol that works with OAuth to control user access to resources. When you use OAuth to determine a user’s authorizations, you can additionally use OIDC to authenticate the user through the use of JSON Web Tokens (JWT).

In this tutorial you will complete the following lessons:
  1. Add OIDC capability to an OAuth native provider
  2. Test OIDC Security

Before you begin

This tutorial uses the predefined FindBranch API and an existing native OAuth provider configured with the "Access code" grant type. To prepare your environment for this tutorial, complete the following tasks:

  1. Add the DataPower® API Gateway gateway service to the Sandbox catalog as explained in Creating and configuring catalogs.

    The Sandbox catalog must be configured to use at least one gateway. For this tutorial, you must use the same gateway that the FindBranch API uses.

  2. Import the FindBranch API and activate it as explained in Tutorial: Importing an API.
  3. Create the MyNativeOAuthProvider native OAuth provider as explained in Tutorial: Implementing OAuth Security.

Add OIDC capability to an OAuth native provider

To add OIDC security to a native OAuth provider, complete the following steps:
  1. Open the OAuth provider for editing:
    1. Log in to API Manager.
    2. On the Home page, click the Manage resources tile.
      Manage Resources tile
    3. In the Resources navigation list, click OAuth Providers.
    4. In the list of OAuth providers, click MyNativeOAuthProvider to open it.
      New OAuth provider
  2. In the Edit Native OAuth Provider navigation list, click OpenID Connect.OIDC form
  3. On the OpenID Connect page, select Enable OIDC.

    OIDC form

  4. If any settings are selected in the Support hybrid response types list on the page, clear the selections.
  5. Select Auto Generate OIDC API Assembly.

    This option updates your API with the flow for OIDC.

    Auto Generate settings

    A message displays to warn that you must provide either an ID token signing crypto object or an ID token signing key. In this tutorial, you provide a JWK key (in the next step).

  6. Click Copy icon to copy the following key, and then paste it in the ID token signing key field:
    { "alg": "HS256", "kty": "oct", "use": "sig", "k": "o5yErLaE-dbgVpSw65Rq57OA9dHyaF66Q_Et5azPa-XUjbyP0w9iRWhR4kru09aFfQLXeIODIN4uhjElYKXt8n76jt0Pjkd2pqk4t9abRF6tnL19GV4pflfL6uvVKkP4weOh39tqHt4TmkBgF2P-gFhgssZpjwq6l82fz3dUhQ2nkzoLA_CnyDGLZLd7SZ1yv73uzfE2Ot813zmig8KTMEMWVcWSDvy61F06vs_6LURcq_IEEevUiubBxG5S2akNnWigfpbhWYjMI5M22FOCpdcDBt4L7K1-yHt95Siz0QUb0MNlT_X8F76wH7_A37GpKKJGqeaiNWmHkgWdE8QWDQ", "kid": "hs256-key" }

    This key is not secure and is only intended for use in this tutorial.

    ID token signing key
  7. In the ID token signing algorithm field, select HS256 as the signing algorithm for this key.

    ID token signing algorithm

  8. Click Save.

Test OIDC Security

Note: Due to Cross-Origin Resource Sharing (CORS) restrictions, the assembly test tool cannot be used with the Chrome or Safari browsers on the macOS Catalina platform.

When you test the new OIDC security in the API Manager Test panel, you complete the same steps that you used for testing the native OAuth provider. The Test panel does not display the JWT token that is received with the access token, so in this tutorial you will obtain the JWT token using cURL commands so that you can verify that the token is returned.

  1. Set up the Test panel to invoke your API:
    1. On the Develop / findbranch page, click the Test tab in the page header.

      The imported FindBranch API already has a definition, which uses a single policy called Invoke to execute the API. This API is ready to test.

    2. To activate the API, click Target Configuration.

      FindBranch API

    3. On the Preferences window, toggle Auto-publish to set the API status to online.

      Test panel

    4. Click Send.

      Test invoke

    5. If a No response received message appears, click Open the server.

      No response message

      A new browser tab opens. If an error message appears, ignore it.

  2. Switch to a command window and use cURL commands to obtain the access token and JWT token that allow you to use the API:
    Note: The authorization code that you receive from the OAuth provider expires after a few minutes. To avoid having to repeat the request, prepare both of the commands for this step as much as possible before executing the first command.
    1. Run the following cURL command to request an authorization code for the API:
      curl -k -i --header "Authorization: Basic dXNlcjpwYXNz"\
       --request GET "Authorization_URL\
      ?redirect_uri=https://example.com/redirect\
      &scope=openid+details\
      &response_type=code\
      &client_id=Client_ID"
      Where:
      • The cURL parameter -k allows cURL to execute your operation even for insecure server connections.
      • The cURL parameter -i includes protocol response headers in the output so that you can view the response in the command window.
      • The authorization header specifies that you will authenticate with the user registry (the AuthURL user registry that you created) using Basic authentication, and provides the password ("pass") encoded in base64.
      • The Authorization_URL is copied from the Test panel.
      • The redirect_uri is the OAuth redirect URL that you configured in the Sandbox Test App.
      • The scope specifies two scopes, concatenated with +: the API's details scope that you will access, and the OIDC scope that authorizes you.
      • The response_type is code because you want to receive an authorization code.
      • The Client_ID is copied from the Test panel's Identification section and ensures that you can access your Sandbox Test App.
      Example:
      curl -k -i --header "Authorization: Basic dXNlcjpwYXNz"\
       --request GET "https://example.com/eb-org/sandbox/mynativeoauthprovider/oauth2/authorize\
      ?redirect_uri=https://example.com/redirect\
      &scope=openid+details\
      &response_type=code\
      &client_id=01c43d1620e0c4e6ded0dec20b5655d9"
      The response looks like the following example:
      HTTP/1.1 302 Found
      Connection: Keep-Alive
      Transfer-Encoding: chunked
      X-RateLimit-Limit: name=default,100;
      X-RateLimit-Remaining: name=default,93;
      User-Agent: curl/7.55.1
      Accept: */*
      X-Client-IP: IP_address
      X-Global-Transaction-ID: 12df8d855e7e18ee00000681
      Location: https://example.com/redirect? code=AALxLnKixp9VIy3PvVKBwfbuTgNbwnZtHB6iS9b_BUw39UZZjUi2CeFdPYJZW0mgqNMtzFUhrsfu3FFiC9aGfHnJ3CqdIANqlo-v-DkQv7ELWw 
      Content-Type: text/xml
      Date: Fri, 27 Mar 2020 15:17:02 GMT
    2. Copy the authorization code (returned in the code parameter) so you can use in the next step.
    3. Run the following cURL command to exchange the authorization code for an access token and a JWT token:
      curl -k -i --header "Content-Type: application/x-www-form-urlencoded"\
       --request POST "Token_URL"\
       --data-urlencode "code=Authorization_code"\
       --data-urlencode "client_secret=Client_Secret"\
       --data-urlencode "grant_type=authorization_code"\
       --data-urlencode "scope=openid details"\
       --data-urlencode "client_id=Client_ID"
      Where:
      • The Token_URL is copied from the Test panel.
      • The Authorization_code is copied from the response to the previous command.
      • The Client_Secret is copied from the Test panel's "Identification" section.
      • The grant_type is "authorization_code".
      • The scope again specifies two scopes (separated with a space in this command because the values are enclosed in quotation marks).
      • The Client_ID is copied from the Test panel's "Identification" section.
      Example:
      curl -k -i --header "Content-Type: application/x-www-form-urlencoded"\
       --request POST "https://example.com/eb-org/sandbox/mynativeoauthprovider/oauth2/token"\
       --data-urlencode "code=AAJ8zz5SvYgxFw0zY0fOxAOiDeaw_PLR6dAFh-ojXVjv-80TB25VGfj28J4Jf7jzgaWVVfLQuVTRSfUbp2hDjYsX9QmZHJOg5p_bfHFWBlQlLg"\
       --data-urlencode "client_secret=d6634763de6c612ae69636d0fc948650"\
       --data-urlencode "grant_type=authorization_code"\
       --data-urlencode "scope=openid details"\
       --data-urlencode "client_id=01c43d1620e0c4e6ded0dec20b5655d9"
      The response looks like the following example:
      {"token_type":"Bearer", "access_token":"AAIgMDFjNDNkMTYyMGUwYzRlNmRlZDBkZWMyMGI1NjU1ZDkm4gPMmFjgv2XXhI7t6LZ8BcIRaO_LvWirsNDlirJWi_7qqKGp_fr5py7yE_fHoD17ajAUJPPuUjsV5xj7go25JQjk_smS-AYvmPXRi99IxQ" ,"scope":"openid details","expires_in":3600,"consented_on":1585322249, "id_token":"eyJraWQiOiJoczI1Ni1rZXkiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI3NjE2OTRiYS1iYjYzLTRlNWQtOTc1ZS04NThkZGYxMmI2ZTkiLCJpc3MiOiJJQk0gQVBJQ29ubmVjdCIsInN1YiI6InVzZXIiLCJhdWQiOiIwMWM0M2QxNjIwZTBjNGU2ZGVkMGRlYzIwYjU2NTVkOSIsImV4cCI6MTU4NTMyNTg1MiwiaWF0IjoxNTg1MzIyMjUyLCJhdF9oYXNoIjoibDZYRDV5SjVuMTU1MkZSV19pR2k2USJ9.IO1RVPWV5zOhYGmCXUvG0_-9OO0guURPwaEbGOqCpCg" }

      The response includes two tokens: the access token and the JWT (labeled id_token). Receiving these tokens verifies that you are authenticated using OIDC and your native OAuth provider.

      Note: If you receive an Invalid request response with an error about an expired code, it means the authorization code expired. Return to substep a and repeat the process to obtain a new authorization code, and then quickly exchange it for the access token and JWT token.
  3. Return to the Test panel and click Send to execute the API.

    You don't need to paste any codes into the Test panel because you used cURL to exchange tokens with API Connect.

    The FindBranch API's response displays the Status code 200 OK and response header information, and the body contains the data for each bank branch.

    Response to successful API call

What you did in this tutorial

In this tutorial, you completed the following activities:
  • Added OIDC security to an existing API.
  • Tested the security by manually requesting an authorization code and exchanging it for an access token plus a JWT token before invoking the API.