403 Response from Adobe Experience Manager OAuth 2 Token endpoint

I use Postman to test OAuth 2 by installing AEM for vanilla.

enter image description here

Postman can successfully obtain an authorization code from / oauth / authorize after granting access:

enter image description here

But when he tries to use the code to get the token from / oauth / token, he gets the following response:

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

In Fiddler, it makes a POST in / oauth / token with the following names / 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 a previous request to oauth / authorize

Did I miss something?

+6
source share
3 answers

I myself found the answer and thought that I would share the process that I went through, as well as the answer, because it can help other people new to AEM.

How to find the cause of the error:

  • Go to CRXDE Lite.
  • Select a console.
  • Then uncheck the stop button to allow new console logs to appear (this is very inconsistent for me).

CRXDE Lite Console

From here I could see the cause of the problem:

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

Since the postman does not put the referrer in the request header, I had to tell Apache Sling to allow empty request headers.

For this:

  • Go to / system / console / configMgr
  • Open Apache Sling Filter Filter Configuration
  • Check the box next to "Allow is empty."

Apache Sling Referrer Filter Configuration

+1
source

It would help if you could list the code snippets on how you create the URL and retrieve the token.

Here is an example of how we implemented very similar to what you are trying to do, perhaps this will help.

Define the service as shown below (snippet) and define the values ​​(host, URL, etc.) in OSGI (or you can also program them for testing)

@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"); //// } } } 
+1
source

A good way to allow this is to list the allowed hosts, otherwise it would run counter to the best practices of the AEM security checklist.

Its subtlety for a development environment is not for production.

0
source

All Articles