Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

403 Response From Adobe Experience Manager OAuth 2 Token Endpoint

I am using Postman to test OAuth 2 from a vanilla AEM install.

enter image description here

Postman can successfully obtain the authorization code from /oauth/authorize after I grant access:

enter image description here

But when it tries to use the code to obtain a token from /oauth/token it receives the following response:

HTTP ERROR: 403 Problem accessing /oauth/token. Reason: Forbidden Powered by Jetty://

Looking in Fiddler it is doing a POST to /oauth/token with the following Name/Values in the body:

client_id: Client ID from /libs/granite/oauth/content/client.html

client_secret: Client Secret from /libs/granite/oauth/content/client.html

redirect_uri: https://www.getpostman.com/oauth2/callback

grant_type: authorization_code

code: Code returned from previous request to oauth/authorize

Am I missing something?

like image 576
GerardBeckerleg Avatar asked Jan 29 '16 02:01

GerardBeckerleg


2 Answers

Would help if you can list some code snippets on how you are building the url and fetching the token.

Here's an example of how we've implemented very similar to what you are trying to do, maybe it'll help.

Define a service like below (snippet) and define the values (host, url, etc) in OSGI (or you can also hard code them for testing purposes)

     @Service(value = OauthAuthentication.class)
     @Component(immediate = true, label = "My Oauth Authentication", description = "My Oauth Authentication", policy = ConfigurationPolicy.REQUIRE, metatype = true)
     @Properties({
       @Property(name = Constants.SERVICE_VENDOR, value = "ABC"),
       @Property(name = "service.oauth.host", value = "", label = "Oauth Host", description = "Oauth Athentication Server"),
       @Property(name = "service.oauth.url", value = "/service/oauth/token", label = "Oauth URL", description = "Oauth Authentication URL relative to the host"),
       @Property(name = "service.oauth.clientid", value = "", label = "Oauth Client ID", description = "Oauth client ID to use in the authentication procedure"),
       @Property(name = "service.oauth.clientsecret", value = "", label = "Oauth Client Secret", description = "Oauth client secret to use in the authentication procedure"),
       @Property(name = "service.oauth.granttype", value = "", label = "Oauth Grant Type", description = "Oauth grant type") })
      public class OauthAuthentication {   
      ...
      @Activate
      private void activate(ComponentContext context) {
         Dictionary<String, Object> properties = context.getProperties();
         host = OsgiUtil.toString(properties, PROPERTY_SERVICE_OAUTH_HOST,new String());

         // Similarly get all values
         url = 
         clientID = 
         clientSecret = 
         grantType = 
         authType = "Basic" + " "+ Base64.encode(new String(clientID + ":" + clientSecret));
      }

      public static void getAuthorizationToken(
         try {
            UserManager userManager = resourceResolver.adaptTo(UserManager.class);
            Session session = resourceResolver.adaptTo(Session.class);

            // Getting the current user                        
            Authorizable auth = userManager.getAuthorizable(session.getUserID());

         user = auth.getID();
         password = ...
         ... 
         ...
         String serviceURL = (host.startsWith("http") ? "": protocol + "://") + host + url;
         httpclient = HttpClients.custom().build();
         HttpPost httppost = new HttpPost(serviceURL);

         // set params
         ArrayList<BasicNameValuePair> formparams = new ArrayList<BasicNameValuePair>();
         formparams.add(new BasicNameValuePair("username", user));
         formparams.add(new BasicNameValuePair("password", password));
         formparams.add(new BasicNameValuePair("client_id", clientID));
         formparams.add(new BasicNameValuePair("client_secret",clientSecret));
         formparams.add(new BasicNameValuePair("grant_type",grantType));

          UrlEncodedFormEntity postEntity = new UrlEncodedFormEntity(formparams, "UTF-8");
          httppost.setEntity(postEntity);

          // set header
          httppost.addHeader("Authorization", authType);
          response = httpclient.execute(httppost);
          HttpEntity entity = response.getEntity();

          if (response.getStatusLine().getStatusCode() == 200) {
            if (entity != null) {
               object = new JSONObject(EntityUtils.toString(entity));
            }
            if (object != null) {
              accessToken = object.getString("access_token");
              ////
            }
          }
      }
like image 118
Suren Konathala Avatar answered Oct 25 '22 17:10

Suren Konathala


I found the answer myself and thought I'd share the process I went through as well as the answer because it might help other people new to AEM.

How to find the cause of the error:

  1. Go to CRXDE Lite.
  2. Select console.
  3. Then deselect the stop button to allow new console logs to appear (this is very counter-intuitive to me).

CRXDE Lite Console

From here I was able to see the cause of the issue:

org.apache.sling.security.impl.ReferrerFilter Rejected empty referrer header for POST request to /oauth/token

Because postman does not place a referrer in the request header I had to tell Apache Sling to allow empty request headers.

To do this:

  1. Go to /system/console/configMgr
  2. Open the Apache Sling Referrer Filter Config
  3. Select the Allow Empty check box

Apache Sling Referrer Filter Config

like image 40
GerardBeckerleg Avatar answered Oct 25 '22 16:10

GerardBeckerleg