AEM as OAuth Server – Part 1 – Setting up Scopes

Usually when we want to implement OAuth in AEM, our requirements are that a user should be able to use their Facebook or google account to show certain details- like profile pic from their social account in the AEM webpage.  In these cases AEM is an OAuth Client and Facebook or Google is the OAuth server. Here the user in AEM is prompted to login into Facebook or Google and authorize AEM to access parts of the their Facebook profile or google account (known as scope of access).

This requirement that is described here is the opposite of that – We have a client who needs authorization to access part of the AEM content. In this case AEM is the OAuth server.

OAuth 2.0 Authorization Framework

This is the OAuth 2.0 Authorization Framework :

Roles in  OAuth Authentication is described here :

Protocol Flow – Authorizaction Grant method is described here :

Adobe’s Granite OAuth2 Server Implementation

Details about Adobe’s Granite OAuth2 Server implementation that we should know : This is as told by Adobe Support –

This is a partial implementation of The OAuth 2.0 Authorization Framework (RFC 6749) (

In particular it (currently) implements only the Authorization Code Grant flow ( It also implements ONLY the “Authorization Request Header Field” (, while the “Form-Encoded Body Parameter” and “URI Query Parameter” are not implemented.

These are the existing documents available for AEM as OAuth Server  which gives us insights on how we should go about implementing Scopes and our Rest APIs, however these are for AEM 6.0 and cannot be applied completely for 6.2 since the Granite OAuth2 server implementation has changed.



How to setup AEM as the OAuth Server

Setup OAuth Client in AEM

OAuth clients can be setup here : Tools -> Security -> OAuth clients.

Once an OAuth client is setup, the client id and client secret is auto generated.

Please note that the redirect url needs to be set  exactly as provided by the client. Apart from the client id and client scret, redirect url is one of the parameters that is used to validate an OAuth client and it must exactly match.

This is a sample client that was setup with the tool “Postman” as the client.

In order to get the callback url of postman for OAuth –

Create a new request in Postman and for Authorization Type use – OAuth 2.0. This shows an option – “Get New Access Token”

The following pop up appears when we click on it. The first entry is the callback url. We will look at all the entries in detail in later sections.

The Callback Url for Postman is :

Setup a client using this callback url.

After clicking on Create Client ID, the client id and client secret are auto generated by AEM.

Now an Oauth Client for Postman is setup in the AEM server.

Enable  Adobe Granite OAuth Server Authentication Handler

We have to make sure that the Adobe Granite OAuth Server Authentication Handler configuration is enabled (com.adobe.granite.oauth.server.auth.impl.OAuth2ServerAuthenticationHandler)


Set up Scopes that the client should be able to access

Implement Scope

Scopes have to be coded by implementing com.adobe.granite.oauth.server.Scope.

Scope implementation Example

package com.techaspect.oAuthExample.core.oauth.scope;

import javax.servlet.http.HttpServletRequest;
import com.adobe.granite.oauth.server.Scope;

public class SampleScopeOne implements Scope {

	public String getDescription(HttpServletRequest httpServletRequest) {
		return "This is a sample scope - One";

	public String getEndpoint() {
		return "/bin/oauth/sample/one";

	public String getName() {
		return "sampleScopeOne";

	public String getResourcePath(User user) {
		return "/content/dam/sample/one";


Implement OAuth2ResourceServer

To setup scopes, the com.adobe.granite.oauth.server.OAuth2ResourceServer has to be re-implemented. This interface has a method – public Map<String, Scope> getAllowedScopes() which should return the new scopes as needed.

Example of OAuth2ResourceServer implementation

package com.techaspect.oAuthExample.core.oauth.impl;

import java.util.HashMap;
import java.util.Map;

import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.adobe.granite.oauth.server.OAuth2ResourceServer;
import com.adobe.granite.oauth.server.Scope;
import com.techaspect.oAuthExample.core.oauth.scope.SampleScopeOne;
import com.techaspect.oAuthExample.core.oauth.scope.SampleScopeTwo;

@Component(label = "SampleOAuth2ResourceServerImpl - OAuth Resource Server", description = "OAuth Resource Server", metatype = true, immediate = true)
public class OAuth2ResourceServerSampleImpl implements OAuth2ResourceServer {

	@Property(intValue = 20000)
	private static final String RANKING = "service.ranking";

	private static final Logger LOG = LoggerFactory.getLogger(OAuth2ResourceServerSampleImpl.class);
	private static Map<String, Scope> allowedScopes = createMap();

	private static Map<String, Scope> createMap() {
		Map<String, Scope> myMap = new HashMap<String, Scope>();
		myMap.put("sampleScopeOne", new SampleScopeOne());
		myMap.put("sampleScopeTwo", new SampleScopeTwo());
		return myMap;

	public Map<String, Scope> getAllowedScopes() {
		if(LOG.isDebugEnabled()) {
			LOG.debug("List of allowed scopes from getAllowedScopes()  : ");
			for (Map.Entry<String, Scope> entry : allowedScopes.entrySet())
				LOG.debug("Allowed Scope : " + entry.getKey() + " : " + entry.getValue().getEndpoint());

		return allowedScopes;


Sample End point

package com.techaspect.oAuthExample.core.servlets;


import javax.servlet.Servlet;
import javax.servlet.ServletException;

import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;

 * Servlet that writes some sample content into the response. It is mounted for
 * all resources of a specific Sling resource type. The
 * {@link SlingSafeMethodsServlet} shall be used for HTTP methods that are
 * idempotent. For write operations use the {@link SlingAllMethodsServlet}.
@Component(service = Servlet.class, property = { Constants.SERVICE_DESCRIPTION + "=Simple Demo Servlet",
		"sling.servlet.methods=" + HttpConstants.METHOD_GET, "sling.servlet.paths=" + "/bin/oauth/sample/one" })
public class SampleOAuthTestServlet extends SlingSafeMethodsServlet {

	private static final long serialVersionUID = 4077423361846561555L;

	protected void doGet(final SlingHttpServletRequest req, final SlingHttpServletResponse resp)
			throws ServletException, IOException {

		resp.getWriter().write("SampleOAuthTestServlet - 1 - /bin/oauth/sample/one!! : User ID : "
				+ req.getResourceResolver().getUserID());


Authorization and Token urls for OAuth in AEM

Autorization url : /oauth/authorize

Token Url : /oauth/token

Example :

Authorization url


Token Url

Token call is a post request and would be something like this. The code is the code  Json Web Token – JWT returned by the authorization end point.

We will see this in more detail in the Testing Blog.

Disable default implementation of OAuth2ResourceServer

Ideally after implementing the Scopes and implementing the OAuth2ResourceServer, we should be done and should be ready to test the setup, however there is one more small step that needs to be done.

In the previous step we have re-implemented/customised com.adobe.granite.oauth.server.OAuth2ResourceServer  to return the new custom scopes. We have set the ranking of this new implementation of OAuth2ResourceServer to 20,000, hoping that this implementation will definitely override the default implementation of OAuth2ResourceServer (which is com.adobe.granite.oauth.server.impl.OAuth2ResourceServerImpl).

However this is not the case.

The default implementation of OAuth2ResourceServer has to be disabled before our implementation is picked up by the OAuth2AuthorizationEndpointServlet.

Here are more details :

Before doing this step (disabling of the default implementation of OAuth2ResourceServer  ) try to access the Authorization url : It would return 400 Bad request with the reason that the scope is invalid. However the scope is correct as per our custom implementation.


To troubleshoot this a bit, checkout the OAuth2AuthorizationEndpointServlet. Notice that the reference for oAuth2ResourceServer is still the default – com.adobe.granite.oauth.server.impl.OAuth2ResourceServerImpl. This default implementation does not have the new scopes that we implemented. This is the reason the authorization url/endpoint returns the invalid scope message.


Checkout the default implementation of OAuth2ResourceServer  – OAuth2ResourceServerImpl. We have to disable this, so that OAuth2AuthorizationEndpointServlet referes to our implementation of OAuth2ResourceServer


Disable this default implementation.

After disabling the default implementation of OAuth2ResourceServer, again see the OAuth2AuthorizationEndpointServlet. Notice that, now the reference for oAuth2ResourceServer refers to our custom implementation.


Now try the Authorization url again : Now it shows the authorization screen asking for our approval. The description of the scopes we setup are shown here.


And now we are done with setting up an OAuth client and setting up scopes and are ready to test this out.

How to test will be explained in Part 2 of this blog.

About The Author

Priya Noohu

AEM Developer

Leave a Reply