Child pages
  • Protect a REST API with OAuth2
Skip to end of metadata
Go to start of metadata

Overview

In this guide we explain how to stand up a mock REST service and protect it with OAuth2 using OpenIG and OpenAM.

This article is based on the following documentation: https://backstage.forgerock.com/#!/docs/openig/4/gateway-guide/chap-oauth2-rs

Prerequisites

The following components are required:

Creating a mock service

The first (optional) step for this is to create a mock service. This can easily be done using Wiremock.

Configure Wiremock:

1. Create a directory called Wiremock: mkdir wiremock

2. Copy the Wiremock standalone jar: cp wiremock-1.57-standalone.jar wiremock

3. Create a directory called mappings. mkdir wiremock/mappings

4. In mappings create a JSON file ( called whatever you like ): vi wiremock/mappings/test.json

{
    "request": {
        "method": "GET",
        "url": "/service/v1.0/test/test"
    },
    "response": {
        "status": 200,
        "body": "Test URL\n"
    }
} 

5. Start Wiremock on your chosen port ( here I used 9999): java -jar wiremock-1.57-standalone.jar -port 9999

6. Check the mock service is running: http://localhost:9999/service/v1.0/test/test

7. You should see "Test URL" in the browser.

Configuring OpenIG

The next step is to configure OpenIG. It is assumed IG is already installed.

1. Create a base and config directory for OpenIG: mkdir -r /usr/local/env/openig/config

2. When you start OpenIG you specify where this config directory is by specifying an environment variable for the base directory: export OPENIG_BASE=/usr/local/env/openig

3.. Ensure openig/config/config.json is configured as below (create if required), choose a port to run IG on (I use 28080 below):

{
    "handler": {
        "type": "Router",
        "audit": "global",
        "baseURI": "http://localhost.localdomain.com:28080",
        "capture": "all"
    },
    "heap": [
        {
            "name": "LogSink",
            "type": "ConsoleLogSink",
            "config": {
                "level": "DEBUG"
            }
        },
        {
            "name": "JwtSession",
            "type": "JwtSession"
        },
        {
            "name": "capture",
            "type": "CaptureDecorator",
            "config": {
                "captureEntity": true,
                "captureContext": true
            }
        }
    ]
} 

4. Create a routes directory: mkdir openig/config/routes

5. Create a mapping under the routes directoryvi openig/config/routes/06-rs.json

http://localhost.localdomain.com:18080/openam/oauth2/tokeninfo should map to your installation of OpenAM.

 

{
    "handler": {
        "type": "Chain",
        "config": {
            "filters": [
                {
                    "type": "OAuth2ResourceServerFilter",
                    "config": {
                        "providerHandler": "ClientHandler",
                        "scopes": [
                            "uid",
                            "userPassword"
                        ],
                        "tokenInfoEndpoint":
                            "http://localhost.localdomain.com:18080/openam/oauth2/tokeninfo",
                        "requireHttps": false,
                        "target": "${attributes.token}"
                    },
                    "capture": "filtered_request",
                    "timer": true
                },
                {
                    "type": "AssignmentFilter",
                    "config": {
                        "onRequest": [
                            {
                                "target": "${session.username}",
                                "value": "${attributes.token.info.uid}"
                            },
                            {
                                "target": "${session.password}",
                                "value": "${attributes.token.info.userPassword}"
                            }
                        ]
                    },
                    "timer": true
                },
                {
                    "type": "StaticRequestFilter",
                    "config": {
                        "method": "GET",
                        "uri": "http://localhost.localdomain.com:9999/service/v1.0/${attributes.token.info.uid}/${attributes.token.info.uid}"
                    },
                    "timer": true
                }
            ],
            "handler": "ClientHandler"
        }
    },
    "condition": "${matches(request.uri.path, '^/rs')}",
    "timer": true
} 

The OAuth2ResourceServerFilter will integrate with OpenAM to protect the service with OAuth2 using the defined scopes.

The AssignmentFilter has been configured to extract scope values from the token and assign them to variables.

The StaticRequestFilter has been configured to remap the request to a REST URL based on the users UID for this example:

Note the uri path under condition, this means that request to: 

http://localhost.localdomain.com:28080/rs

Will be redirected through the gateway to:

http://localhost.localdomain.com:9999/service/v1.0/${attributes.token.info.uid}/${attributes.token.info.uid}

Configuring OpenAM

Now we need to configure OpenAM.

1. Create an OAuth 2.0 Authorization server in the top level realm.

2. Create an OAuth 2.0 client profile with:

client_id = OpenIG

client_secret = password

3. Edit the client profile you just created and configure the scopes to match the OpenIG filter:

Invoking the service with OAuth2

All being well, you should now be able to request an OAuth2 bearer token and use it to invoke the REST service:

1. Request a bearer token:

"OpenIG:password" - OAuth 2.0 client credentials you just configured in OpenAM.

"username=test&password=Abcd1234" - The username and password of a user in OpenAM.

curl --user "OpenIG:password" --data "grant_type=password&username=test&password=Abcd1234&scope=uid%20userPassword" "http://localhost.localdomain.com:18080/openam/oauth2/access_token"

2. Invoke the service using the bearer token returned from the OpenAM access_token endpoint. Note the service is being invoked via the OpenIG route we defined earlier on 28080.:

curl --header "Authorization: Bearer e4add7ce-4ebd-4839-802b-624a6df6dcde" "http://localhost.localdomain.com:28080/rs" 

3. You should see "Test URL" returned from the mock service.

 

  • No labels