Error: Public clients can't send a client secret while try to get access token in Onedrive - onedrive

I am trying to get OneDrive access token by following URL
https://login.live.com/oauth20_token.srf?client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&redirect_uri=https://login.live.com/oauth20_desktop.srf&code=AUTHORIZATION_CODE&grant_type=authorization_code
but the response is as following
{"error":"invalid_request","error_description":"Public clients can't send a client secret."}
Can anyone explain this?

A "public client" is a mobile or desktop application (web services are "confidential clients"). MSA is giving you this response because you're redirecting to https://login.live.com/oauth20_desktop.srf. In this case, you should not be providing the client_secret value in the request, so your request should just look like this:
https://login.live.com/oauth20_token.srf?client_id=YOUR_CLIENT_ID&redirect_uri=https://login.live.com/oauth20_desktop.srf&code=AUTHORIZATION_CODE&grant_type=authorization_code

A more recent example from:
https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow
Request an access token with a client_secret
Now that you've acquired an authorization_code and have been granted permission by the user, you can redeem the code for an access_token to the resource. Redeem the code by sending a POST request to the /token endpoint:
// Line breaks for legibility only
POST /{tenant}/oauth2/v2.0/token HTTP/1.1 Host:
https://login.microsoftonline.com Content-Type:
application/x-www-form-urlencoded
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&scope=https%3A%2F%2Fgraph.microsoft.com%2Fmail.read
&code=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1aXxUjq3n8b2JRLk4OxVXr...
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&grant_type=authorization_code
&code_verifier=ThisIsntRandomButItNeedsToBe43CharactersLong
&client_secret=JqQX2PNo9bpM0uEihUPzyrh // NOTE: Only required for web apps. This secret needs to be URL-Encoded.
Parameter
Required/optional
Description
tenant
required
The {tenant} value in the path of the request can be used to control who can sign into the application. Valid values are common, organizations, consumers, and tenant identifiers. For more information, see Endpoints.
client_id
required
The Application (client) ID that the Azure portal – App registrations page assigned to your app.
scope
optional
A space-separated list of scopes. The scopes must all be from a single resource, along with OIDC scopes (profile, openid, email). For more information, see Permissions and consent in the Microsoft identity platform. This parameter is a Microsoft extension to the authorization code flow, intended to allow apps to declare the resource they want the token for during token redemption.
code
required
The authorization_code that you acquired in the first leg of the flow.
redirect_uri
required
The same redirect_uri value that was used to acquire the authorization_code.
grant_type
required
Must be authorization_code for the authorization code flow.
code_verifier
recommended
The same code_verifier that was used to obtain the authorization_code. Required if PKCE was used in the authorization code grant request. For more information, see the PKCE RFC.
client_secret
required for confidential web apps
The application secret that you created in the app registration portal for your app. Don't use the application secret in a native app or single page app because a client_secret can't be reliably stored on devices or web pages. It's required for web apps and web APIs, which can store the client_secret securely on the server side. Like all parameters here, the client secret must be URL-encoded before being sent. This step is usually done by the SDK. For more information on URI encoding, see the URI Generic Syntax specification. The Basic auth pattern of instead providing credentials in the Authorization header, per RFC 6749 is also supported.
So, if creating a desktop or mobile app and if you registered your app as such in the Azure portal at https://portal.azure.com/ then if you send client_secret you would get that particular error. So you must remove it from the POST request to successfully exchange received code for authentication token and refresh token. Note that confidential web app is the only type which requires to send client_secret. Other types of registered apps or public apps should not send the client_secret.
The code is valid for 10 minutes so it must be immediately exchanged for authentication token using the request similar to the above.
Note one more thing:
Whether or not you'll need to send a client_secret depends whether or not you've registered your application in AzureAD as "web" (requires sending client_secret) or "native app" (does not require sending the client_secret). So your implementation will depend on the registration you did. You can change the type of application in AzureAD -> App Registrations -> select Authentication from the left menu. Under the Platform Configurations choose your specific platform.

Related

ID token usage when using "Log in with Google" in a mobile app

Suppose that I have a mobile app with a frontend and a backend server.
My understanding is that -- when a user logs in the app with "Login with google", the frontend sends a request to the google auth server, and gets back an ID token. The documentation says that the frontend can then send the token to the backend server to establish a session. I imagine that means the token can be used in session-based authentication?
If I were to use token-based authentication (as opposed to session-based), do I just attach the ID token in every server request, and have the backend verifies it each time when processing a request? this page suggests the ID token should not be sent to the backend API. Which leaves me wonder what the correct procedure is for token-based authentication when using log in with Google.
So my question is: Does my server need to create an access token from the ID token from Google, and send it to the frontend, so the frontend can attach that access token in the API requests for authentication?
Thanks
Login with Google is an identity provider (IDP) operation. A full OAuth solution, including an authorization server (AS) looks like this:
Mobile app uses system browser to redirect to AS
AS returns a redirect response to the system browser, which routes to the IDP
User signs in at the IDP
IDP returns an authorization code to AS
AS swaps it for IDP tokens and carries out validations
AS issues a set of tokens to the app. This includes an access token (AT) with whatever scopes and claims are needed for business authorization to work.
Mobile app sends AT in API requests
API authorizes using scopes and claims from the access token
So ideally plug in an authorization server, to get this out-of-the-box behaviour. Another option is to implement your own token service, and issue your own tokens. That is less recommended though, since it requires more detailed understanding of the underlying security.

OAuth2 2-legged client credentials flow and "confidential" clients -- how to hide the client_secret

I have a REST api that accepts what are essentially anonymous survey responses, i.e., from non-authenticated users. My organization wants to allow a few (maybe 12) partners to develop client apps to collect the responses and send them to the api. I want the api to authenticate these clients, i.e., validate that the client is one of the 12 that we've authorized. I was planning to use the OAuth 2 "client credentials" flow, providing each of these clients with a unique client_id and client_secret. The client would request a token using their client_id and client_secret, and then use that token in subsequent api calls. The clients would be required to be https server-based apps that can keep the client_secret hidden -- i.e., "confidential clients" for the purposes of the OAuth2 spec (https://www.rfc-editor.org/rfc/rfc6749#page-14).
But can the client_secret really be confidential in the client credentials flow? As I understand it, the recommended way to pass the client_id and client_secret is as a base64-encoded value in the HTTP Basic auth header. If an attacker browses to that client app to submit a suryvey response, can't he just use the browser dev tool to see the base64-encoded client_id:client_secret value, decode it, and build his own app using that same client_id and client_secret?
I know I can use CORS to restrict browser-based requests to those from the 12 authorized domains. So I guess I'm really asking about non-browser attacks that try to impersonate one of the authorized clients.
So my questions:
Am I right that this visible base-64 encoded version of the client_id:client_secret presents a vulnerability in a vanilla OAUth2 2-legged client credentials flow (i.e., no end-user to authorize the client)?
Instead of client credentials, I'm thinking we could use a signed-token approach (probably JWT), similar to what's described here, where:
the client server and api server have a shared private key.
the client generates a token, signing it with a hash of the private key plus a timestamp. The client sends that token in the api request, along with the "request timestamp" used for the hash.
the api server validates the token, using the private key and the "request timestamp" to verify the hash. The server accepts only recent timestamps (e.g., within the last 2 seconds) to prevent replay attacks.
Does that sound like a reasonable approach?
Can anyone think of another way to restrict the api to only authorized clients?

Is HTTP Basic Authentication and OAuth 2.0 same?

One of a vendor API documentation mentions that their API calls require to use HTTP Basic Authentication scheme, i.e. user:password Base64 encoded but, their token API (Login equivalent) documentation mentions that "..this service implements OAuth 2.0 - Resource Owner Password & Credential Grant"
Isn't HTTP Basic Authentication different from OAuth ?
Yes, HTTP Basic Authentication different from OAuth 2.0. However, the Resource Owner Password Credentials Grant utilizes Basic Authentication Scheme within the Authorization Request for the Client's credentials as described with section 4.3.1. Authorization Request and Response
The Resource Owner Password Credentials Grant is typically used to convert legacy systems to OAuth 2.0 and no more secure than Basic Authentication Scheme.
Resource Owner Password Credentials Grant is intended to be used when no other Grant Types are available and ONLY when there is a high degree of trust between the Resource Owner and the OAuth Client .
Yes, they both are different.
Http Basic : This is for authentication and user credentials are encoded then passed in HTTP header to the client server.
Basic example for HTTP Basic : Just like traditional web application which asked user to provide credentials and these credentials sent to server in HTTP header. Later server utilize those credentials to authenticate the user.
OAuth 2 : This is for authorization, here the client server required authorization of user data(resource owner) from authorization server.
Basic example for OAuth 2 : Let say there is a online game application running on a server, the user accessed the application which starts loading into user's browser. Now that application asking grants from user to post data about games on his Facebook account. Here user authorize his that application to access his Facebook posts through OAuth Standard. Refer the internal mechanism https://www.rfc-editor.org/rfc/rfc6749
Basic access authentication usage is comparable to OAuth 2.0 Client Credentials Grant Type.
A session can be created using Basic Authentication and services can be accessed using a sessionid in a stateful environment.
But if you do not want to use the session due to session limitations or stateless services, you can use the OAuth 2.0 Client Credentials Grant Type instead, which creates a token instead of session and sessionid. This token provides access to the services.
HTTP basic access authentication:
This is the simpler method for meeting the requirements to access a web service. It is simple because it doesn’t require any of the usual processes in a credentials system: cookies, session IDs or access pages. The whole HTTP basic authentication process is based on standard fields in the HTTP header. Thus, it avoids handshaking: the automated process by which two entities establish authenticated communication before starting normal communication via the established channel. This means equipment can communicate with an external device only if there is successful authentication; otherwise, the communication channel is not created. The connection via modem would fail, for example. The secure development of the basic HTTP access authentication method is HTTPs.
To prevent the basic HTTP access authentication method causing the browser to launch a username and password request for each access, the browser must store this information in the cache for a prudent length of time that doesn’t reduce security excessively. These security credentials are usually stored for 15 minutes.
What is this basic HTTP access authentication method like in the real world?
The access credential provided to third-party developers who want to connect to a mobile API is a totally secret alphanumerical ID.
This alphanumerical API key is stored in a secure space on the server.
The developer making requests for a particular service contained in this API should place this secret ID within the HTTP authorization header along with the word Basic. The two elements together allow the server to recognize the alphanumerical credential and provide access.
GET /private/index.php HTTP/1.1
Host: example.com
Authorization: Basic alphanumerical ID
OAuth 2.0:
OAuth represents a step forward in the use of credentials for authentication of API service users. It is a major advance on the basic HTTP access authentication method. Today it is practically the only security method that is almost 100% reliable, and its reliability is based on creating unique authentication tokens for each user. If this access token is compromised, it is deleted and a new one is issued. This means that the API’s own credentials are safeguarded.
The authentication process is as follows:
A user launches a native application and is asked to give a username or email address and a password to identify themselves as a user.
The type of request used to send this credential to the API is a POST request, which ensures private delivery of secret data. This request is sent via the SSL (Secure Sockets Layer) protocol, designed to enable applications to transmit outbound data securely. SSL facilitates giving and receiving encryption keys between applications.
This request allows to validate user credentials and to create ad hoc an authentication or access token that will expire after a time, or if the user or developer responsible for the API believes it to have been breached.
This authentication token is stored in the device to facilitate access to the API’s services that support the application itself.
If we compare both methods, OAuth 2.0 provides better security criteria because any initial request for credentials is made under the SSL protocol and because the guaranteed access object is a temporary token. In the basic HTTP access authentication process, access to API services always relies on sending credentials via the web, specifically in the HTTP header, which makes it much vulnerable to third parties.

Azure API Management OAuth 2.0 Resource Owner Password Flow Client ID

Context:
My software application is a multi-tenant application that customers can log into and generate their own clientIDs to use with a resource owner password flow OAuth Request.
Our OAuth 2.0 authorization server is built in WebAPI and inherits from the Microsoft provided Microsoft.Owin.Security.OAuth.OAuthAuthorizationServerProvider class.
Currently, we only support one flow (resource owner password) to get a token, which looks like:
POST /api/v1.0/token HTTP/1.1
Host: api.mysoftwareapp.com
UserName={username}&Password={password}&grant_type=password&client_id={client_id}
After we validate the credentials & client ID, we send back an access token generated by the Microsoft.Owin.Security.OAuth.OAuthAuthorizationServerProvider base class. In order to access a resource, a user would need to supply the access_token in the Authorization header as a Bearer token. Client ID is not required to be passed in again. Example below:
GET /api/v1.0/Partners HTTP/1.1
Host: api.mysoftwareapp.com
Authorization: Bearer this_is_where_the_token_goes
I'd like to implement the developer portal feature of Azure API management and allow for my customers to be able to input their own username, password, and client ID when making test calls, so they get data back in the context of their tenant (and ultimately - enable rate limiting by client ID).
In the publisher portal, under Security->OAuth 2.0, I've:
Only checked the Resource owner password grant type.
Specified my authorization request method as POST.
Added my token endpoint URL.
Added grant_type / password as an additional body parameter.
Left the resource owner password credentials blank.
I've also done the following since they were required, but I believe does not apply due to only supporting resource owner password flow, and handling client registrations through my own application:
Added my authorization endpoint URL.
Selected 'In the Body' as my client authentication method.
Added fake client credentials.
Added a fake client registration page URL.
Here's a screenshot of that:
When I navigate to the developer portal and view an endpoint, I can select 'Resource onwer password' under my Auth server. However, when I select this, a popup shows that only lets me input my username and password, NOT my client ID.
How do I set up Azure API Management to allow a user to also specify the client ID they would like to use when setting up authorization - or would we need to change our API to require the client ID when making calls to specific resources instead of when requesting a token?
This is what I'd need:
In order to pass these values in the POST body, you need to change the client authentication method from "basic" to "post".
Go to Publisher Portal security, and modify the OAuth2 server settings to be like the below:

Where to place login dialog for 3-legged Auth for restful API

I'm trying to wrap my head around 3-legged authentication to secure a restful API.
Currently I have a client application at app.host.com which needs to be accessed by multiple users with different account permissions and data, as well as the JSON RESTful api which holds all data at app_api.host.com
For 3-legged auth, I understand I first need a consumer key and secret belonging to the client app.host.com... I also understand an unauthorized request token must be provided by the service provider, which is given to the client, which is then redirected back to the service provider for authorization with a login dialog.
So does the login dialog then exist as a user interface on the API host at app_api.host.com? Doesn't this defeat the purpose of me building a purely JSON restful API separately to the client?
Or can I build the login dialog on the client which would then post the user/pwd details to another auth endpoint on the API and provide a 200 code when the request token is authorized? And then in turn the client would ask for permissions from the user which would again be posted to another endpoint which then responds with the appropriate access token for that user?
TL;DR: Am I able to have the login dialog exist on the client, which then posts data to the service provider? All guides I've read suggest having the dialog on the service provider, which in this case would defeat the purpose of having the api as a separate app altogether. How should I go about building this? Any available guides?
OAuth 2.0 defines different flows to use with different clients, depending on how much you trust the client.
Authorization code
The first and most secury flow is the authorization token flow. It is used with a traditional web application in which you can store secrets relatively securely (only people with admin privileges should have access to the client ID and secret stored in the configuration).
When the user (resource owner) wants to authenticate, the user-agent is redirected to the authorization server which belongs to the domain of the resource server (the data the client wants to consume, for example Facebook or Google). The authorization server presents the user with logon UI. When the user authenticates successfully, it presents the consent UI to ask if the user wants the client application to access the resource. If the user consents, the user-agent is redirected back to the client application with an authorization code. The client application can now use this code, its client ID and secret to talk to the authorization server directly and get an access token. In this flow, the access token is never in the hands of the user-agent.
Implicit flow
In the implicit flow, the user-agent (here typically a native (mobile) application or JavaScript client) redirects to the authorization server or opens a browser window to navigate to the authorization server. When the user authenticates successfully and grants permission to the client application, the access token itself is returned to the client. So the user-agent never sees the username and password the user enters (as this happens on a HTML page that is controlled by the resource server), but does have control over the access token.
Resource owner password credential flow
Here the user-agent is fully trusted and asks the user for username and password. It then communicates with the authorization server to get a access token. Even though the user-agent knows the credentials of the user, it only uses them once to get an access token. It does not need to send them along each request to the resource server.
So to answer your question, you can build the login dialog in your app if you think your users will trust your application enough to give you their credentials. Otherwise you should probably go for one of the other flows. You can read more on OAuth 2 here and here.