Maybe you have created an interesting application and would like to allow your clients to share your API with other applications. You would possibly also want to authorize different parts of your API to different clients. For example for an FBI account you want to give access to a lot of resources in your platform so they can check the earnings of every person in your company to determine whether everything is in order. Perhaps to a writer, you only want to grant access to the articles written on your server. With OAuth 2.0, you are able to achieve the above scenario whereby an end user may explicitly authorize access to a client application without having to share credentials (with this client application). For more details on how Oauth 2.0 works, kindly look here.
Twitter, Facebook and other applications already use OAuth 2.0. This allows you to grant partial profile access to external applications such as Gmail. Permitting you to send post messages and import friends lists for example.
How to use an OAuth 2.0 server in a Mule application?
Ok, let’s start with the basic stuff.
1. Define the namespaces ‘oauth-provider’ to configure OAuth and ‘mule-ss’ for authentication manager:
<mule xmlns:ss="http://www.springframework.org/schema/security" xmlns:mule-ss="http://www.mulesoft.org/schema/mule/spring-security" xmlns:spring="http://www.springframework.org/schema/beans" ... version="EE-3.3.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ... xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd http://www.mulesoft.org/schema/mule/spring-security http://www.mulesoft.org/schema/mule/spring-security/current/mule-spring-security.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
2. We need a security-manager that references an authentication manager to identify which users can use our application:
<spring:beans> <ss:authentication-manager id="resourceOwnerAuthenticationManager"> <ss:authentication-provider> <ss:user-service id="resourceOwnerUserService"> <ss:user name="john" password="doe" authorities="READ_PROFILES"/> </ss:user-service> </ss:authentication-provider> </ss:authentication-manager> </spring:beans> <mule-ss:security-manager> <mule-ss:delegate-security-provider name="resourceOwnerSecurityProvider" delegate-ref="resourceOwnerAuthenticationManager"/> </mule-ss:security-manager>
In this case we have a user with username ‘john’ and password ‘doe’ with role RESOURCE_OWNER.
3. Now it’s time to create the OAuth 2.0 provider where we configure the type of login/access to get an access_token.
First we specify the clients that can access using OAuth; for that we have the “clients” element in the oauth-provider.
Of course we need to distinguish between users and clients, as these are not the same. Clients are third party applications (not ours) which will connect with our API. Users are the users in our application.
To understand this better, imagine Twitter. You are a user of Twitter and you want to allow another application, called ‘tweetread’, which connects with your Twitter account to import your friends list. In this case you are the user (you used your username and password of the Twitter application to login on Twitter). The client is ‘tweetread’ which has a client id and secret password registered in the Twitter app. In this way, Twitter knows that ‘tweetread’ is secure.
*Note: ‘tweetread’ doesn’t exist, it is just an example.
Below is the configuration for an OAuth client in Mule:
<oauth2-provider:config> <oauth2-provider:clients> <oauth2-provider:client clientId="myclientid" secret="myclientsecret" type="CONFIDENTIAL" clientName="Mule Bookstore" description="Mule-powered On-line Bookstore"> <oauth2-provider:redirect-uris> <oauth2-provider:redirect-uri>http://localhost*</oauth2-provider:redirect-uri> </oauth2-provider:redirect-uris> <oauth2-provider:authorized-grant-types> <oauth2-provider:authorized-grant-type>AUTHORIZATION_CODE</oauth2-provider:authorized-grant-type> </oauth2-provider:authorized-grant-types> <oauth2-provider:scopes> <oauth2-provider:scope>READ_RESOURCE</oauth2-provider:scope> <oauth2-provider:scope>POST_RESOURCE</oauth2-provider:scope> </oauth2-provider:scopes> </oauth2-provider:client> </oauth2-provider:clients> <oauth2-provider:config/>
As you can see, every client has a different “client id” and a “secret” that is like a password for that client. The type of client can be “PUBLIC” or “CONFIDENTIAL”. PUBLIC means that it doesn’t need to validate client credentials, we will use “CONFIDENTIAL” in this example. Every client has a redirect-uri, that we use to get the access_token using an access_code, this is explained in more detail later.
The authorized-grant-type and scopes shall also be explained later on.
So far we have defined the client inside the oauth2 provider. Next we configure the type of access.
Type of access in the Oauth provider
There are several types of access called “Oauth grant types” available:
- Authorization code – Has 2 steps:
- Login in a form (this form is created automatically by the provider).
- Get an access_code and then you must use the acces_code in a different url to get the access_token.
- Implicit - Similar to above but requires only 1 step, you login and you get the access_token.
- Resource owner password credentials – The access_token is obtained from step 1) but you have to specify the username and password in the POST request so it makes it less secure because the client needs to have the ability to handle the user’s credentials.
- Client credentials: In this case you get the access_token without the username and password, you only need the clientId, clientSecret and the scope.
The Authorization-code grant type is meant for general use and is the most secure of all the grant types; we use this for our example. You can get more information about the others in the section “Oauth grant types” here.
Configuring the grant type as Authorization_code:
<oauth2-provider:config name="oauth2Provider" providerName="SampleAPI" supportedGrantTypes="AUTHORIZATION_CODE" port="8081" authorizationEndpointPath="sampleapi/api/authorize" accessTokenEndpointPath="sampleapi/api/token" resourceOwnerSecurityProvider-ref="resourceOwnerSecurityProvider" scopes="READ_RESOURCE POST_RESOURCE" doc:name="OAuth provider module"> <oauth2-provider:clients> <oauth2-provider:client clientId="myclientid" secret="myclientsecret" type="CONFIDENTIAL" clientName="Mule Bookstore" description="Mule-powered On-line Bookstore"> <oauth2-provider:redirect-uris> <oauth2-provider:redirect-uri>http://localhost*</oauth2-provider:redirect-uri> </oauth2-provider:redirect-uris> <oauth2-provider:authorized-grant-types> <oauth2-provider:authorized-grant-type>AUTHORIZATION_CODE</oauth2-provider:authorized-grant-type> </oauth2-provider:authorized-grant-types> <oauth2-provider:scopes> <oauth2-provider:scope>READ_RESOURCE</oauth2-provider:scope> <oauth2-provider:scope>POST_RESOURCE</oauth2-provider:scope> </oauth2-provider:scopes> </oauth2-provider:client> </oauth2-provider:clients> </oauth2-provider:config>
We have added new attributes to the “oauth2-provider:config” tag:
supportedGrantTypes – where the grant type is defined.
authorizationEndpointPath - is the url called to get the access_code and accessTokenEndpointpath - is the url called to get the access_token.
resourceOwnerSecurityProvider-ref – references the security provider that we created earlier.
In order to test this example, we send a request to:
This sends the access_code to the redirect-uri that we specified for that client. Then that client sends a request to:
This returns the access_token to the client and we save that access_token in a store (This store is already configured by default in memory for mule, but you can also configure this to use a database if preferred).
The access_token that is returned is a key that grants access to the restricted areas in the API for that client.
READ_RESOURCE – is a “permission constant token”, you can name that token as you want, for example; READ_POSTS. The “permission constant token” is used to access the API flows in Mule, so if the user has this permission constant token, then he has access to that flow.
For example; the following flow will return a message, in this case “hello world!” using the READ_RESOURCE permission:
<flow name="protected-resource" doc:name="DemoRestRouterFlow1"> <http:inbound-endpoint address="http://localhost:8082/resources" doc:name="HTTP" /> <oauth2-provider:validate config-ref="oauth2ProviderPassword" throwExceptionOnUnaccepted="true" doc:name="Validate Token" scopes="READ_RESOURCE" /> <set-payload value="hello world!" /> </flow>
In order to invoke the above flow from the same machine where it is hosted, use the following URI:
In cases where the permission of the user is not correct, an InvalidAccessTokenException exception is thrown.