May 5, 2020
Estimated Post Reading Time ~

Adobe Granite OAuth Authentication Handler



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 that 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
Nowadays 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 exist 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 implement 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 uses 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 providers already configured :



These are the mentioned Facebook and Twitter provider.

In order to use a new Provider you need:
  1. Create a new bundle in which you implements the Provider class
  2. Create an app on the provider in order to obtain the clientId and clientSecret
  3. Add a new configuration for the OAuthAuthenticationHandler using this data
  4. Use the configId of the previous step to create an authentication URL
Be sure to enable the oauth authentication handler in the 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 your new osgi component.

One of the methods 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 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 extend.

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 deploying your new bundle you can configure in system console the baseUrl for your api in the auth.oauth.provider.opb.name section (add localization for this label too!). These are general property available for the provider and nothing specific for a single-use (like clientId)

After obtaining 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 applied 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 gets 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 an 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 redirect your browser to the provider authentication form.

AUTHORS
Marco Re



By aem4beginner

No comments:

Post a Comment

If you have any doubts or questions, please let us know.