Salesforce returning "unsupported_grant_type" - salesforce

We implemented OAuth 2.0 using Web Server Authentication Flow. It was working fine in October/November but all of a sudden it has stopped working. Whenever we try authorising another client the server return (400) Bad Request with the body
{"error":"unsupported_grant_type","error_description":"grant type not supported"}
grant_type is set as authorization_code which is definitely valid.
Is there any reason why OAuth would suddenly stop working?
This is how we have implemented OAuth:
First user is directed to: https://login.salesforce.com/services/oauth2/authorize?response_type=code&client_id=blah.id&redirect_uri=https://domain.com/Web/Salesforce/Callback.aspx&scope=api%20refresh_token
User is prompted by Salesforce to login to their account.
Once user is authenticated Salesforce calls Callback.aspx, Callback.aspx requests refresh token on behalf of the client by making a POST request to: https://login.salesforce.com/services/oauth2/token with the payload:
grant_type=authorization_code&code=blah.code&client_id=blah.Id&client_secret=11111111&redirect_uri=https://domain.com/Web/Salesforce/Callback.aspx
Content type is definitely: application/x-www-form-urlencoded

After lot of fiddling around with fiddler figured out there was a space before grant_type=authorization_code in HTTP POST payload that was causing the issue.
Interestingly that space has been there in code base since July and this issue was first noticed on 14th Jan. It is possible Salesforce fixed a bug or made an internal change to reject space before grant_type=authorization_code.

Make sure you are using 'https' not http
If you are having this error while authorising an Org through terminal sfdx command -
error authenticating with auth code due to: grant type not supported
Worked for me 'https' solved my grant type not supported problem.

Related

IdentityServer API unauthorized if hosted in IIS

I added additional API to the Duende IdentityServer 6.2 as described here. Then I tried to access it from a sample App, using typed httpClient using their own library called AccessTokenManagement (aka Identity.Model) pretty much following their simple example. I use Authorization Code flow, everything pretty much simple and default.
It works well until both server and client are on the same dev machine under localhost. As soon as I publish IdentityServer to IIS, the API stops to work, while the rest still works well (I can be authenticated, and I see in the Fiddler that token exchanges work normally).
The call to API consists from two calls:
Calling to /connect/token using refresh token. Server returns access token.
Calling my endpoint using this new access token.
The flow fails on the step 1. Call to /connect/token is already unauthorized and I can't understand why. The "good" and "bad" calls looks the same, I cannot see any differences. Previous call moment ago to /connect/userinfo consists of the same two steps and it works. Logs on both server and client give no clues.
No reverse proxies, just good plain simple URI. Automatic key management is enabled and the keys are in the SQL table, common for dev and published server. Asp.Net Core Data Protection is enabled and keys are also common.
Relevant parts of logs are below. I noticed that "No endpoint entry found for request path" is specific to IdentityServer and it doesn't actually mean that endpoint was not found. It was found but not processed. I also noticed reacher response headers from bad request and log entry about "Cookie signed-in" in good request but not sure what does it mean and whether it's relevant.
I'm running out of ideas.
Bad response from IIS while trying to get new Access Token:
Proper response while developing:
///////Relevant part of log for BAD request
|Duende.AccessTokenManagement.OpenIdConnect.UserAccessAccessTokenManagementService|Token for user test#test.com needs refreshing.
|Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler|AuthenticationScheme: cookie was successfully authenticated.
|Duende.AccessTokenManagement.OpenIdConnect.UserTokenEndpointService|refresh token request to: https://auth.mysite.org/connect/token
|Duende.AccessTokenManagement.OpenIdConnect.UserAccessAccessTokenManagementService|Error refreshing access token. Error = Unauthorized
|System.Net.Http.HttpClient.IdsService.ClientHandler|Sending HTTP request POST https://auth.mysite.org/mycontroller/myaction
|System.Net.Http.HttpClient.IdsService.ClientHandler|Received HTTP response headers after 117.7278ms - 401
///////Same part of GOOD request
|Duende.AccessTokenManagement.OpenIdConnect.UserAccessAccessTokenManagementService|Token for user test#test.com needs refreshing.
|Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler|AuthenticationScheme: Cookies was successfully authenticated.
|Duende.AccessTokenManagement.OpenIdConnect.UserTokenEndpointService|refresh token request to: https://localhost:5001/connect/token
|Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler|AuthenticationScheme: Cookies signed in.
|System.Net.Http.HttpClient.IdsService.ClientHandler|Sending HTTP request POST https://localhost:5001/mycontroller/myaction
|System.Net.Http.HttpClient.IdsService.ClientHandler|Received HTTP response headers after 1994.9611ms - 200
///////Server log during BAD request
Duende.IdentityServer.Hosting.EndpointRouter No endpoint entry found for request path: "/mycontroller/myaction"
Duende.IdentityServer.Hosting.LocalApiAuthentication.LocalApiAuthenticationHandler HandleAuthenticateAsync called
Duende.IdentityServer.Hosting.LocalApiAuthentication.LocalApiAuthenticationHandler AuthenticationScheme: "IdentityServerAccessToken" was not authenticated.
Duende.IdentityServer.Hosting.LocalApiAuthentication.LocalApiAuthenticationHandler AuthenticationScheme: "IdentityServerAccessToken" was challenged.
Okay, found it. Thankfully, looked at Fiddler's WebView and had seen familiar picture!
Then, found this topic. The solution was disabling Basic authentication in IIS settings. Access token request has basic authentication header and it seems like IIS intercepts it. Still a bit unclear why other parts of flow worked.

Amazon SP API getting internal server error

I am trying to get access token from api https://api.amazon.com/auth/o2/token
POST /auth/o2/token HTTP/l.l
Host: api.amazon.com
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
grant_type=refresh_token
&refresh_token=Aztr|...
&client_id=foodev
&client_secret=Y76SDl2F
But after POST request I get 500 server error.
Is it because my app is in draft status? or I am missing something while making request?
If it because of draft status then when the status will get change? any thoughts on this.
Thank you for your help in advance.
The documentation is wrong. I was getting the same exact error and came across this comment on a github issue which mentioned that the data has to be passed into the body of the request, not as query string parameters. Sure enough, this worked for me and I was able to get an access token. So just to clarify: grant_type, refresh_token, client_id, and client_secret should be passed into the body of the POST request to https://api.amazon.com/auth/o2/token and NOT as query string parameters.
Draft status will not keep you from requesting and receiving the access token.
Here are a few things to check as not much can be derived from the example post request from the documentation:
Did you configure AWS IAM role / policy / user properly
Did you use the correct IAM ARN when registering the application
Are you using the correct LWA credentials (I am assuming you're not passing foodev and Y76SDl2F as those are example parameters)
Have you self authorized the application (are you using the refresh token generated
for the authorized application)
Are you 'assuming the role' before the token exchange -- this is a very important step
and is very different in comparison to how access was handled with MWS -- if
you have not, the server will reject the token exchange regardless if the refresh
token is correct. More on that here
This is a non-exhaustive list, just some common issues I have seen other developers have with getting the access token during development, if these don't work you'll need to work with support as they can see the requests hitting the token endpoint.

Authorization request to get access on behalf of a user results in a 'cookiesDisabled' page

I'm trying to do an Authorization request following the documentation about it on Microsoft (Getting access on behalf of a user: https://learn.microsoft.com/en-us/graph/auth-v2-user). I'm making the request using Azure's Logic Apps. I already made an app registration in Azure AD and gave it the following permissions (I used the app for a few different requests before so that's why it contains a lot of unnecessary api permissions). I already succeeded in getting access without a user (https://learn.microsoft.com/en-us/graph/auth-v2-service). Now I really don't know what I'm doing wrong, so if anybody has an idea of what it is, please let me know. I will try to explain as carefully as possible using screenshots so you guys get the idea of what I'm trying to do.
On the first screen below you can see the api permission I added to my app registration. For this request I'm only asking authorization for the one with arrow next to it(as you will see later on).
On the second screen you can see the HTTP post request I'm trying to make to the authorize endpoint. I blurred out the Tenant and Client_id for privacy reasons. I only added the required parameters in the body as described by Microsoft. In the scope parameter you can see the api permission I'm asking permission for.
On the third screenshot you can see the output of the request. Instead of getting an Authorization code as requested, I get an HTML body.
When I paste that HTML body into a browser it gives me the following result:
I have no clue what I'm doing wrong. I tripled checked to make sure cookies are enabled, made sure third-party cookies are not disabled and added login.microsoftonline to my trusted websites.
I'm starting to think I'm doing something very simple wrong, but I can't figure out exactly what. Any help is welcome! :D
Sorry can't add a comment so posting as an answer
What you are trying to implement is the Authorization Code grant flow of OAUTH 2.0. In Authorization code grant flow following steps occur
1) User is presented with the scopes that an application requires when accessing certain resources,
2) The user authorizes this. and the user is redirected to a redirect url
3) The application then exchanges the code sent with the redirect url to get the actual token which in this case will be sent to the Microsoft Graph for validation.
4) User then sees the information pulled.
The major crux of Authorization Code grant flow is that "User Authorization is required" This basically means that this flow is used when the call is invoked from a browser client where the user is actually interacting. This flow should not go through the Azure Logic Apps. If you want a service or a daemon to access the resources in that case you should use Client Credentials Grant flow

Acquiring a token for graph.microsoft.com with adal.js

I've been using Azure Active Directory and adal.js to authorize web apps client side and it's worked great. Recently had a request to have user photo instead of a generic user icon.
I added Microsoft Graph permissions to the app registration. And tried to get a token for the user photo request like...
authContext.acquireToken('https://graph.microsoft.com', callback);
Which resulted in the response_type 'token' is not supported for the application error. So I found ADAL JS - response_type="token" is not supported suggesting setting "oauth2AllowImplicitFlow": true in the app manifest, which I did. Now I get Token renewal operation failed due to timeout error.
I've also added 'https://graph.microsoft.com': 'https://graph.microsoft.com' to the endpoints prop of the context config.
What do I have to do get this working? Way too much time spent just trying to get users' photos. Thanks.

Delete groups in Microsoft Graph API in C#

I get an authorization 401 error code when I try to delete a Group from the API in C# but if I try it in postman it succeeds. Feels kinda weird because I run the same command but it doesn't work...
The problem I think I have is that to DELETE a group in Office 365 I need to login to my account and that the application can't makes this action.
I gave all Group.ReadWrite.All access and all other permissions for the application. So I think I need to pass my Login credentials for Azure AD or am I incorrect.
Request :
StatusCode: 401,
ReasonPhrase: 'Unauthorized',
Version: 1.1,
Content: System.Net.Http.NoWriteNoSeekStreamContent,
Headers:
EDIT
I tried to not use my GetAccessToken() and use the token I got when using OAUTH 2.0 verification in Postman. If I took that bearer token I had no problem running my script and using DELETE.
So my question what the difference of using ADAL in C# code and the call that Postman Auth2.0. When using Postman I get a login page where I login to my Azure account, can I replicate this in code? For the authentication in C# I use this example.
NEW EDIT
As one wrote in the chat, I checked the access token and what roles I had on a website.
roles: [
"EduRoster.Read.All",
"Mail.ReadWrite",
"User.ReadWrite.All",
"Calendars.Read",
"People.Read.All",
"Group.Read.All",
"Directory.ReadWrite.All",
"MailboxSettings.Read",
"Contacts.ReadWrite",
"Group.ReadWrite.All",
"Notes.Read.All",
"Directory.Read.All",
"User.Read.All",
"Mail.Read",
"Calendars.ReadWrite",
"Mail.Send",
"MailboxSettings.ReadWrite",
"Contacts.Read",
"Member.Read.Hidden",
"Notes.ReadWrite.All"]
Some clarification: If you have a token and it doesn't have the necessary claims/permissions to make the API call you are trying, you'll should get a 403 Forbidden. If the token is missing in the API request or malformed, you'll get a 401 Unauthorized. Please see https://developer.microsoft.com/en-us/graph/docs/concepts/errors.
Are you making direct HTTP REST calls to Graph, or are you using the client library? I suggest that you look at some of our samples to get started for examples of token acquisition together with calls to Microsoft Graph. Try https://github.com/microsoftgraph/console-csharp-snippets-sample (uses a .Net client library) or https://github.com/microsoftgraph/aspnet-connect-rest-sample (uses direct HTTP REST calls).
Also are you acquiring a token in the context of a (signed-in) user, or in the context of the application (no signed in user)? If the former, you need to request a "delegated" permission. If the latter, you need to request an "application" permission. Please see these concepts: https://developer.microsoft.com/en-us/graph/docs/concepts/auth_v2_user and https://developer.microsoft.com/en-us/graph/docs/concepts/auth_v2_service
Hope this helps,
You're on the right track.
The Delete Group method support both Delegated (Authorization Code or Implicit OAUTH grants) and Application (Client Credentials OAUTH grant) models. Both Delegated and Application flows require the Group.ReadWrite.All scope.
The reason you're getting a 401 Unauthorized error is that your application hasn't received Admin Consent for the tenant you're connected too. When using Client Credentials there is no User to authenticate so before your application can interact with the tenant, an Admin must first explicitly authorize your application and the scopes you're requesting.
You can find a walk through at v2 Endpoint and Admin Consent.

Resources