This guide shows you how to implement OAuth security in Exposed REST APIs. To follow this guide, you will need the “OAuthSample” component from the forge.
The guide applies to OutSystems Platform 9.0.1 and onwards.
OAuth is a very popular open standard for authorization to allow third party applications to access data in behalf of the users.
OutSystems Platform allows you to customize the authentication logic to be used with REST APIs and, this way, implement OAuth:
Set the REST API to use custom authentication.
This adds an OnAuthentication callback action to your REST API. It will be executed for every incoming request to this REST API, before executing the method's action flow.
In the OnAuthentication callback, implement the OAuth logic to obtain an access token.
If the validation is successful, login using the access token.
We have an application to manage contacts. It has the 'ContactsAPI' REST API with a method called 'GetContacts' that provides the list of all Contacts. To see how to create a REST API , please read Expose Data using REST.
We want to use OAuth to authenticate applications calling REST API methods that we expose.
For your reference, you can find this example in the OAuthSampleAPI module of the “OAuthSample” component. Three modules are included:
OAuthSampleProvider - Includes all the logic related to OAuth.
OAuthSampleAPI - Sample API that uses OAuth for authentication.
OAuthSampleConsumer - Simulates what a third party client would do when accessing a REST API protected with OAuth.
We have to set the authentication mode for the REST API:
Go to the Logic tab and expand the 'Integrations' folder;
Select the 'Contacts' REST API. In the properties pane, set the 'Authentication' property to 'Custom'.
As a result, you have the 'OnAuthentication' callback action added to your REST API.
In this example we will implement a custom authentication logic, where the REST API expects to receive an Authorization header with the format “Bearer <access_token>”.
In the 'OnAuthentication' action flow, follow these steps to implement the authentication logic:
Use the GetRequestHeader action of the HTTPRequestHandler module to get the Authentication header that is received in the request.
Use the access token to authenticate. One way to do this is using the LoginWithAuthToken action from the OAuthProvider module provided in the sample. This action will automatically raise an exception if the access token is invalid or expired.
If the Authentication header is not present in the request, you should raise an exception. To do that, add a RaiseError element and choose to create a new UserException in the “Select Exception” dialogue. The message should be meaningful, like “Authorization header is missing in the request”. Learn more about User Exceptions;
If the Authentication header is present, but does not have the format “Bearer <access_token>”, you should reply with a Bad Request:
Set the status code to 400 using the SetStatusCode action of the HTTPRequestHandler;
Raise an User Exception, and remember to set an appropriate message, such as “Missing Bearer token in the Authorization header”.
To test the REST API you just created, you will need an API test application like Postman or curl. You also need to replace all the the references to "YourServer", both in the OAuthSampleConsumer and in this guide, by the address of your Platform Server (e.g.: "johndoe.outsystemscloud.com")
After deploying the module to your environment, we test the method with a curl command:
curl -k https://<YourServer>/OAuthSampleAPI/rest/Contacts/GetContacts
The result is a response with status code 500. The message body contains the error message you added when raising the User Exception:
"Authorization header is missing in the request."
That was the expected result, since we need a valid access token to access the API. To get an access token follow the steps below.
To implement OAuth authentication in your API you need to have an OAuth provider that handles the user authorization and token granting process. The sample component includes the OAuthSampleProvider module that implements the “Authorization Code” flow of granting access tokens. The flow below summarizes the steps necessary for a Client Application to get an access token to access a Protected API.
Before starting the flow, it is necessary to register the client application. The OAuthSampleProvider module already comes with one registered client, with the following values:
Name: Contacts Test App
If you wish to add more client applications, you should add new records to the Client entity.
The client application will navigate to the authorization page of the OAuth provider. The following parameters are necessary:
The id of the client application. This application must be previously registered in the OAuth provider.
Identifies the expected response. For this flow, it should be “code”.
URL to where the user should be redirected after granting authorization.
The state parameter is a random object that is used to prevent Cross-Site Request Forgery attacks.
For this example, please open this page on your browser:
The user will now be prompted to enter his username and password.
After logging in, the user must grant authorization to the third party application to access his data.
After the user granted permission, the browser will be redirected back to the client application to the redirect_uri provided in Step 1, returning the authorization code.
For this example, we created a callback screen the returned authorization code. The browser will redirect to an URL similar to this:
If in step 1 the “state” parameter was added to the URL, the callback redirect will also have this parameter in the response URL, with the same value that was given.
If you selected Yes in Step 3, you should now be in a screen similar to this:
Now that the client application received an authorization code, it must obtain an access token, by doing a request to the token endpoint of the OAuth provider. The following parameters are necessary:
The secret of the client application. It’s the equivalent of the password for the client.
Identifies the type of grant used. For this case it will be “authorization_code”
A valid authorization code.
Let’s again use curl to get the access token. Remember to replace <code> with the authorization code returned in step 4.
curl -k "https://<YourServer>/OAuthSampleProvider/rest/oauth/GetToken?client_id=ghjfxdfAvs596vcGfsvf0ef1&client_secret=6tsdgdjl9fsKDd5zsvnwmdjosDmrufbs93susadLHDvjfhbnwtTRbsnucnrb&grant_type=authorization_code&code=<code>"
Postman alternative (paste the above URL and toggle the Params button to easily change each one):
If everything went well, the OAuthProvider should have responded with something like this:
The “expires_in” attribute in the response indicates for how many seconds will the token be valid. After this time, you will need to redo all the steps to get a new token.
Now that the client application has a valid access token, it can access the protected API. In the example below replace <token> with the access_token you got in the previous step.
curl -k -H "Authorization: Bearer <token>" https://<YourServer>/OAuthSampleAPI/rest/Contacts/GetContacts
Postman alternative (don’t forget to add the authorization header in the Headers tab):
The response should be a list of contacts with Id,Name, JobTitle, Phone and Email.
"Name": "Abel Pasquale",
"Name": "Adam Dimaggio",
"JobTitle": "Sales Agent",
"Phone": "(907) 555-7587",
"Name": "Alan Pryor",
"Phone": "(171) 555-1718",
To know more about OAuth, you can visit the following websites:
OAuth 2.0 Standard - The official specification for the OAuth 2 Authorization Framework.
OAuth Bible - A simple reference guide for both OAuth 1.0 and OAuth 2.
OAuth 2.0 Community Page - Website with various OAuth 2 related content, including implementation examples and links to APIs protected with OAuth.