403 Response From Adobe Experience Manager OAuth 2 Token Endpoint
Asked Answered
P

3

6

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?

Pines answered 29/1, 2016 at 2:45 Comment(0)
P
2

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

Pines answered 11/3, 2016 at 4:24 Comment(0)
C
2

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");
              ////
            }
          }
      }
Chap answered 2/2, 2016 at 18:51 Comment(3)
Thanks for responding. I am using the Oauth functionality in Postman to build the urls and fetch the token you can download it for free from here. If you take a vanilla install of AEM 6.1 and add a new Oauth client and then use the client details in Postman then you will have recreated my scenario. I'm from a .NET background so tried building a .NET client to but that returned a 403 too when trying to post to /oauth/token.Pines
I may have misunderstood. Can you try the url's on Publish(4503) environment, see if it makes any difference.Chap
Same issue when running on Publish(4503) environment.Pines
P
2

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

Pines answered 11/3, 2016 at 4:24 Comment(0)
C
0

Good way to allow this to list the allowed hosts, otherwise this is against best practices for AEM security checklist.

Its fine for development environment not for production.

Childbearing answered 19/10, 2016 at 14:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.