OpenIG As an OAuth 2.0 Resource Server OpenIG helps integrate applications into OAuth 2.0 deployments. In this chapter, you will learn to use OpenIG as an OAuth 2.0 Resource Server. This chapter explains how OpenIG acts as an OAuth 2.0 Resource Server, and follows with a tutorial that shows you how to use OpenIG as a resource server. About OpenIG As an OAuth 2.0 Resource Server The OAuth 2.0 Authorization Framework describes a way of allowing a third-party application to access a user’s resources without having the user’s credentials. When resources are protected with OAuth 2.0, users can use their credentials with an OAuth 2.0-compliant identity provider, such as OpenAM, Facebook, Google and others to access the resources, rather than setting up an account with yet another third-party application. In OAuth 2.0, there are four entities involved: Resource owner: The user who owns protected resources on a resource server. For example, a resource owner has photos stored in a web service. Resource server: Provides the user’s protected resources to authorized client applications. In OAuth 2.0, an authorization server grants the client application authorization based on the resource owner’s consent. For example, a web service holds user’s photos. Client: The application that needs access to the protected resources. For example, a photo printing service needs access to the user’s photos. Authorization server: The service responsible for authenticating resource owners and obtaining their consent to allow client applications to access their resources. For example, OpenAM can act as the OAuth 2.0 authorization server to authenticate resource owners and obtain their consent. Other services can play this role as well. Google and Facebook, for example, provide OAuth 2.0 authorization services. In OAuth 2.0, there are different grant mechanisms whereby the client can obtain authorization. One grant mechanism involves the client redirecting the resource owner’s browser to the authorization server to complete authentication and authorization. You might have experienced this grant mechanism yourself when logging in with your identity provider account to access a web service, rather than creating a new account directly with the web service. Whatever the grant mechanism, the client’s aim is to get an OAuth 2.0 access token from the authorization server. Access tokens are the credentials used to access protected resources. An access token is a string given by the authorization server that represents the authorization to access protected resources. An access token, like cash, is a bearer token. This means that anyone who has the access token can use it to get the resources. Access tokens therefore must be protected, so requests involving them must go over HTTPS. The advantage of access tokens over passwords or other credentials is that access tokens can be granted and revoked without exposing the user’s credentials. When the client requests access to protected resources, it supplies the access token to the resource server housing the resources. The resource server must then validate the access token. If the access token is found to be valid, then the resource server can let the client have access to the resources. When OpenIG acts as an OAuth 2.0 resource server, its role is to validate access tokens. How an access token is validated is technically not covered in the specifications for OAuth 2.0. Typically the resource server validates an access token by submitting the token to a token information endpoint. The token information endpoint typically returns the time until the token expires, the OAuth 2.0 scopes associated with the token, and potentially other information. In OAuth 2.0, the token scopes are strings that can identify the scope of access authorized to the client, but can also be used for other purposes. For example, OpenAM maps them to user profile attribute values by default, and also allows custom scope handling plugins. In the tutorial that follows, you configure OpenIG as a resource server, and use OpenAM as the OAuth 2.0 authorization server. Preparing the Tutorial Getting Started describes how to configure OpenIG to proxy traffic and capture request and response data. You also learned how to configure OpenIG to use a static request to log in with hard-coded credentials. You will learn how OpenIG can act as an OAuth 2.0 resource server, validating OAuth 2.0 access tokens and including token info in the context. This tutorial relies on OpenAM as an OAuth 2.0 authorization server. As an OAuth 2.0 client of OpenAM, you get an access token. You then submit the access token to OpenIG, and OpenIG acts as the resource server. Before you start this tutorial, prepare OpenIG and the minimal HTTP server as described in Getting Started. OpenIG should be running in Jetty, configured to access the minimal HTTP server as described in that chapter. Edit config.json to make sure that the CaptureDecorator also captures the context. After you make the changes, the object declaration appears as follows: { "name": "capture", "type": "CaptureDecorator", "config": { "captureEntity": true, "captureContext": true } } Restart Jetty for the changes to take effect. This allows you to view the token information that OpenAM returns. Setting Up OpenAM As an Authorization Server Install and configure OpenAM on http://openam.example.com:8088/openam with the default configuration. If you use a different configuration, make sure you substitute in the tutorial accordingly. Although this tutorial does not use HTTPS, you must use HTTPS to protect access tokens in production environments. Login to the OpenAM console as administrator, and configure an OAuth 2.0 authorization server in the top-level realm. In the console for OpenAM 12 and earlier, use the common task wizard. In the console for OpenAM 13 and later, access the wizard for the realm from Dashboard > Configure OAuth Provider > Configure OAuth 2.0. Create an OAuth 2.0 Client profile in the top-level realm. This allows you to request an OAuth 2.0 access token on behalf of the client. In the console for OpenAM 12 and earlier, browse to Access Control > / (Top Level Realm) > Agents > OAuth 2.0 Client. In the console for OpenAM 13 and later, select the top-level realm and browse to Agents > OAuth 2.0/OpenID Connect Client Then click New in the Agent table. Give the new OAuth 2.0 client profile the name OpenIG and password password. The name is the OAuth 2.0 client_id, and the password is the client_secret. Edit the OpenIG client profile to add mail and employeenumber scopes to the Scope(s) list, and then save your work. Here, you overload these profile settings to pass credentials to OpenIG. This tutorial uses mail and employeenumber for the sake of simplicity. Both of those attributes are part of a user’s profile out of the box with the default OpenAM configuration. Neither of the attributes are needed for anything else in this tutorial. So, this tutorial uses mail to hold the username, and employeenumber to hold the password. In a real deployment, you would no doubt use other attributes that depend on how the real user profiles are configured. Create a user whose additional credentials you set in the Email Address and Employee Number fields if you have not already done so for another tutorial: In the console for OpenAM 12 and earlier, under Access Control > / (Top Level Realm) > Subjects > User, click New to create the user profile. In the console for OpenAM 13 and later, select Subjects in for the top level realm and create a new subject. Set the ID to george, the password to costanza, and fill the other required fields as you like before clicking OK. Click the user name to edit the profile again, setting Email Address to george and Employee Number to costanza before clicking Save. When finished, log out of OpenAM console. Configuring OpenIG As a Resource Server To configure OpenIG as an OAuth 2.0 resource server, you use an OAuth2ResourceServerFilter as described in OAuth2ResourceServerFilter(5) in the Configuration Reference. The filter expects an OAuth 2.0 access token in an incoming Authorization request header, such as the following: Authorization: Bearer 7af41ddd-47a4-40dc-b530-a9aa9f7ceda9 The filter then uses the access token to validate the token and to retrieve token information from the authorization server. On successful validation, the filter creates a new context for the authorization server response, at ${contexts.oauth2}. The context is named oauth2 and can be reached at contexts.oauth2 or contexts['oauth2']. The context contains data such as the access token, which can be reached at contexts.oauth2.accessToken or contexts['oauth2'].accessToken. Filters and handlers placed after the OAuth2ResourceServerFilter in the chain, can access the token info through the context. If no access token is present in the request, or token validation does not complete successfully, the filter returns an HTTP error status to the user-agent, and OpenIG does not continue processing the request. This is done as specified in the RFC, OAuth 2.0 Bearer Token Usage. To configure OpenIG as an OAuth 2.0 resource server, add a new route to the OpenIG configuration by including the following route configuration file as $HOME/.openig/config/routes/06-rs.json: { "handler": { "type": "Chain", "config": { "filters": [ { "type": "OAuth2ResourceServerFilter", "config": { "providerHandler": "ClientHandler", "scopes": [ "mail", "employeenumber" ], "tokenInfoEndpoint": "http://openam.example.com:8088/openam/oauth2/tokeninfo", "requireHttps": false }, "capture": "filtered_request", "timer": true }, { "type": "AssignmentFilter", "config": { "onRequest": [ { "target": "${session.username}", "value": "${contexts.oauth2.accessToken.info.mail}" }, { "target": "${session.password}", "value": "${contexts.oauth2.accessToken.info.employeenumber}" } ] }, "timer": true }, { "type": "StaticRequestFilter", "config": { "method": "POST", "uri": "http://app.example.com:8081", "form": { "username": [ "${session.username}" ], "password": [ "${session.password}" ] } }, "timer": true } ], "handler": "ClientHandler" } }, "condition": "${matches(request.uri.path, '^/rs')}", "timer": true } On Windows, the file name should be %appdata%\OpenIG\config\routes\06-rs.json. Notice the following features of the new route: The OAuth2ResourceServerFilter includes a client handler to perform the following tasks: Send access token validation requests. Provide the list of scopes that the filter expects to find in access tokens. Provide the OpenAM token info endpoint used to validate access tokens. Set "requireHttps": false to allow testing without having to set up keys and certificates. (In production environments, do use HTTPS to protect access tokens.) After successfully using the token info endpoint to validate an access token, the OAuth2ResourceServerFilter creates a new context for the authorization server response, at ${contexts.oauth2.accessToken}. The context contains the access token and the other info returned by the token info endpoint. The AssignmentFilter accesses the token info through the context, and injects the credentials from the user profile in OpenAM into session. The StaticRequestFilter retrieves the username and password from session, and replaces the original HTTP GET request with an HTTP POST login request that contains the credentials to authenticate. The route matches requests to /rs. Testing the Configuration To try your configuration you get an access token from OpenAM and use it to access OpenIG, which uses the OAuth 2.0 resource owner password credentials authorization grant. To Test the Configuration In a terminal window, use a curl command similar to the following to retrieve the access token: $ curl \ --user "OpenIG:password" \ --data "grant_type=password&username=george&password=costanza&scope=mail%20employeenumber" \ http://openam.example.com:8088/openam/oauth2/access_token { "access_token":"aba19a55-468d-45e2-b1c4-decc7202faea", "scope":"employeenumber mail", "token_type":"Bearer", "expires_in":3599 } In the following command, replace <access_token> with the access token returned by the previous step, and then run the command: $ curl \ --header "Authorization: Bearer <access_token>" \ http://openig.example.com:8080/rs ... <h1>User Information</h1> <dl> <dt>Username</dt> <dd>george</dd> </dl> <h1>Request Information</h1> <dl> <dt>Method</dt> <dd>POST</dd> <dt>URI</dt> <dd>/</dd> <dt>Headers</dt> <dd style="font-family: monospace; font-size: small;">...</dd> </dl> What is happening behind the scenes? After OpenIG gets the curl request, the resource server filter validates the access token with OpenAM, and creates a new context for the authorization server response, at ${contexts.oauth2.accessToken}. If the access token had been missing or invalid, then the resource server filter would have returned an error status to the user-agent, and the OAuth 2.0 client would then have had to deal with the error. OpenIG captures the token information into the log, and the AssignmentFilter injects the credentials into the session context. Finally, the StaticRequestFilter uses the credentials to log the user in to the minimal HTTP server, which responds with the user information page. OpenIG As a SAML 2.0 Service Provider OpenIG As an OAuth 2.0 Client or OpenID Connect Relying Party