Header Content Footer
Discover best selling sofas, Lounge chairs and get an extra 10% off using the code SEDONA10

Introduction

OAuth is an authentication protocol that allows you to approve one application interacting with another on your behalf without giving away your password.

Every day new websites launch offering services which tie together functionality from other sites, typically using some API.

OAuth started in 2006 in Twitter labs when they start to think on delegate authentication on their API to build new integrated applications, without asking users to share their Twitter usernames and passwords with all those services.

Ever since two main OAuth specification has been defined:

  • OAuth 1.0 in 2007 and a derived OAuth 1.0a
  • OAuth 2.0

Nowaday most of the web applications that share their API with other services use these protocols allowing growing new applications or new integrated services using an authentication delegation.

Things like IFTTT or Microsoft Flow can’t exists without this protocol.

Using OAuth in Adobe AEM

If you want to delegate user authentication in AEM to Facebook or Twitter or whatever service offering an OAuth endpoint you can but you need to get your hands dirty.

There is an available implementation OOTB for Twitter and Facebook and a good guide on how to configure it in Adobe official documentation (https://docs.adobe.com/docs/en/aem/6-2/administer/communities/social-login.html )

However knowing how Granite Authentication works, you can implements also your preferred provider.

In this topic we cover the steps you need to follow to add a new oauth provider.

The general com.adobe.granite.auth.oauth.impl.OAuthAuthenticationHandler use the concept of Provider to delegate the oauth flow to whatever service you are using.

In the following image from system console you can see that out of the box there are two provider already configured :

These are the mentioned Facebook and Twitter provider.

In order to use a new Provider you need:

  • Create a new bundle in which you implements the Provider class
  • Create an app on the provider in order to obtain the clientId and clientSecret
  • Add a new configuration for the OAuthAuthenticationHandler using this data
  • Use the configId of the previous step to creare an authentication URL

Be sure to enable the oauth authentication handler in osgi console by opening  Adobe Granite OAuth Authentication Handler configuration and save it (without any change!)

 

Get hands dirty

In this example we want to use the Open Bank Project API that implements an OAuth1.0a flow.

After creating a new AEM project (with the Adobe AEM Archetype) add a new class like this one :

@Service({Provider.class})
@Component(metatype=true, label="%auth.oauth.provider.opb.name", description="%auth.oauth.provider.opb.description")
@Properties(
		{
		@org.apache.felix.scr.annotations.Property(name="oauth.provider.id", value={"opb"}),
		@org.apache.felix.scr.annotations.Property(name="opb.api.base.url", value={""})
		}
)
@Reference(name="providerExtension", referenceInterface=ProviderExtension.class, bind="bindProviderExtension", unbind="unbindProviderExtension", cardinality=ReferenceCardinality.OPTIONAL_MULTIPLE, policy=ReferencePolicy.DYNAMIC)
public class OpenBankProvider implements Provider{

...........SKIPPED......

@Activate
	  protected void activate(ComponentContext componentContext)
	    throws Exception
	  {
	    this.name = OsgiUtil.toString(componentContext.getProperties().get("service.description"), "");
	    
	    this.id = OsgiUtil.toString(componentContext.getProperties().get("oauth.provider.id"), "");
	    
	    this.opb_base_url = OsgiUtil.toString(componentContext.getProperties().get("opb.api.base.url"), "");
	    this.api=new OpenBankAPI(this.opb_base_url);
	    
	    this.log.debug("activating provider id {}", this.id);
	  }

 public Api getApi()
	  {
	    return this.api;
	  }
...........SKIPPED......
}

that define you new osgi component.

One of the method you need to define is the getApi that returns to the OAuth Authentication Handler an object of class org.scribe.builder.api.Api.

Scribe is a great java library , very useful when you need to delegate authentication to OAuth providers. It is now at version 4.0 and has already the basic API object for the major providers (about 30 )…Suddenly there is no the Open Bank API and moreover the version supported in AEM is the 1.3 (where is defined the interface  org.scribe.builder.api.Api that you need to implements).

In order to proceed add this dependencies in your pom:

<dependency>
  <groupId>com.adobe.granite</groupId>
  <artifactId>com.adobe.granite.scribe</artifactId>
  <version>1.3.0.B002</version>
</dependency>

Now you can add your new OpenBankAPI class that implements org.scribe.builder.api.Api . Actually Scribe provides also default abstract classes (one for the oauth1.0a e one for oauth2.0) that you can extends.

public class OpenBankAPI extends DefaultApi10a {
	private final Logger log = LoggerFactory.getLogger(getClass());
	String baseUrl = "";

	public OpenBankAPI(String baseUrl) {
		super();
		this.baseUrl = baseUrl;
	}

	@Override
	public String getAccessTokenEndpoint() {
		return baseUrl + "/oauth/token";
	}

	@Override
	public String getRequestTokenEndpoint() {
		return baseUrl + "/oauth/initiate";
	}

	@Override
	public String getAuthorizationUrl(Token token) {
		return baseUrl + "/oauth/authorize?oauth_token=" + token.getToken();
	}

}

The main role of OpenBankAPI is to define the relative path of the provider endpoints. See also some other example here

The other methods in OpenBankProvider that you need to implements are mainly involved in how you need to parse and use user data: what you need to do when creating the user or update the user…..a full example for Linkedin Provider is available here

After deploy your new bundle you can configure in system console the baseUrl for your api in the auth.oauth.provider.opb.name section (add a localization for this label too!) . These are general property available for the provider and nothing specific for a single use (like clientId)

After obtain clientId and clientSecret from your provider ( for open bank api you need to go here , register your application and use consumerKey and consumerSecret), you can add a new configuration for the Adobe Granite OAuth Application and Provider.

In the form all parameters are self explanatory, by the way in this first step you need to set clientId and clientSecret:

After saving the form a configId will be apply to this configuration.

Write down this id because this is what you need to add it in the url to activate our authentication.

The Adobe Granite OAuth Authentication Handler get invoked when you request an URL that ends with /j_security_check. It checks that a parameter configId is in the request and if is available a Oauth Provider is selected using this configId

To check that all is working correctly put your browser to :

http://localhost:4502/j_security_check?configid=op4da2dbc7a22ad11bacb8e39ef92929 with your configid value.

This should be redirect you browser to the provider authentication form.

AUTHORS

Marco Re

REFERENCES

https://oauth.net/core/1.0/

https://oauth.net/core/1.0a/

https://oauth.net/2/

http://www.connectcon.ch/content/dam/cqcon/Pr%C3%A4sentation_Antonio_Sanso.pdf

https://docs.adobe.com/docs/en/aem/6-2/administer/communities/social-login.html

https://github.com/Adobe-Marketing-Cloud/aem-communities-oauth-sample/blob/master/bundles/aem-communities-oauth-linkedin-provider/src/main/java/com/adobe/social/sample/oauth/impl/LinkedinProviderImpl.java

https://github.com/scribejava/scribejava