Goal: I have api hosted in azure - app service. Authentication is set to use azure ad. I have an app host externally. I'm trying to make a simple request but keep getting access denied.
After creating two apps in Azure ad, one for backend api(web api app service authentication configured to use registered app) and one for client app(required permission granted access to first app), I make a call to get the the access token, I get a token- client credential grant. When I use that token to make a call to an API, I get an access denied.
From scouring through all the docs, my understanding is that by registering the two apps and granting permission for client app to access the backend app, when you get the access token by using the client credential(client_id +secret), you should be able to make a request to the backend app with the token. I'm not going through api management. Is there something i'm missing(obv i'm missing something)? Is there an app service setting that i'm overlooking? Any suggestion would be great.
Hope you are using below method. Can you send the exact error message,
https://learn.microsoft.com/en-us/azure/active-directory/develop/v1-oauth2-client-creds-grant-flow
Related
I currently have an API that I am opening up to our business partners to call, and I want it secured with OAuth.
I've set up an Azure API management (consumption plan right now) that points to our API in azure.
I can call it and get valid results in the test console.
So I was following the Microsoft documentation for this, and it had me :
Register my backend API in app registrations;
Register a client app in app registrations;
In azure AD grand the permissions for this client app;
Configure the APIM with a validate-jwt policy.
So now my APIM is returning a 403 as expected.
My question is this. I do not know the clients that will be using this API. Or rather, do I HAVE to register a client app registration? Or can I leave that part out, and just provide the URLS that I have for the OAUTH side, which are like :
https://login.microsoftonline.com/GUID/oauth2/v2.0/authorize
https://login.microsoftonline.com/GUID/oauth2/v2.0/token
I am very new to Oauth and APIM, so I am not even sure how all this works.
But it seems odd that I am registering an app for a client, when I have no information on them or how they are calling my API.
I kinda get that I need to know who is requesting the token and authorizing. But the clients will be using a javascript snippet that we give them to embed on their site, so I dont really know what their site is like, what their URL is or anything.
Hope that makes sense.
The client registration is what represents the entity (web app, mobile app, etc.) that requests for tokens from Azure AD for your API.
The docs walk you through a process where the developer portal is registered as the client.
The snippet in your case would also require a Client ID (of an app) to fetch the token with. For this, you would have to register a new app registration and share the Client ID as part of the snippet.
I have an backend API in an Azure Website that I like to protect using Azure AD.
As I understand it I'll first do an App Registration, use information registration as part of the sign in to get a token back to the client.
I can then send that token to the API and validate the token in the backend API to verify it.
But don't that token give access to all resources in the subscription? How to I restrict the App Registration to only be allowed to access that specific API? And not also another API in the subscription?
I also like to have a set of users that are allowed to access the API. If I'll just allow everyone to log in using the App Registration, everyone that's in my AD will receive a token back?
Can I somehow use a Enterprise Application to restrict access to the API only and only allow a set of users?
Or is there another way of doing this?
But don't that token give access to all resources in the subscription? How to I restrict the App Registration to only be allowed to access that specific API? And not also another API in the subscription?
A token only gives access to the API identified by the audience (aud) claim in the token.
Nothing more.
So if your client app asks for an access token to your API, that token is only valid on that API.
I also like to have a set of users that are allowed to access the API. If I'll just allow everyone to log in using the App Registration, everyone that's in my AD will receive a token back?
Can I somehow use a Enterprise Application to restrict access to the API only and only allow a set of users?
Yes.
You can find the enterprise app (service principal) for the API, enable Require user assignment, and then assign the users/groups you want to have access to the API from Users/Groups tab of the enterprise app.
Access token acquisition will then fail for users who are not assigned.
If you are using the same app registration for both the client and API, then you have to remember that you should acquire an access token regardless to call the API.
Don't use the id token.
Also in that case, a user who is not assigned to the app will fail login.
I am writing a google drive desktop application and I am using OAuth 2 to get credentials. I can get creds for just reading, but not changing files. As it is a desktop application, there is no site. It is written in https://developers.google.com/identity/protocols/oauth2/native-app, that I need to "supply a local redirect URI to handle responses from Google's authorization server". So, should the client also be a server and listening on some port locally? If I want to have the app verified, I need to provide Authorized domains and other stuff, but it is a desktop application, again. Or maybe there is a way to allow users to use the app, but with a warning on a consent screen for example for development purposes.
Also how to hide the credentials, that I use to get the token? If I publish the app with the credentials, everybody can just steal them and use them
In order to develop a desktop application which will use the Drive API you will have to use credentials of the web app type for which you will later provide the appropriate redirect URI.
By using OAuth 2.0 in your application, you are the only one who has access to the credentials for the application - unless you share them.
According to the Google OAuth 2.0 documentation:
You start by obtaining the OAuth 2.0 client credentials from the Google API Console. Then your client application requests an access token from the Google Authorization Server, extracts a token from the response, and sends the token to the Google API that you want to access.
For the login process, when the users will log-in to your application, they will use their own credentials and then they will have to authorize the application you have built in order to be able to use the Drive API.
Reference
OAuth 2.0 for Mobile & Desktop Apps;
Using OAuth 2.0 to Access Google APIs;
Not sure if that is possible: I would like to switch from server flow to native client flow in order to provide a better authentication experience for my users.
The problem is that Azure AppService requires a "web application" OAUTH setup (contains client ID and a secret), while the native login works with just a client ID and not secret. This means that after the login on the phone, I do have a Google token, but AppService wouldn't know what to do with it and returns me an HTTP Unauthorized.
The mobile client SDK gives me an API, but that doesn't work with such a token.
var jObject = new JObject(
new JProperty("access_token", auth.AccessToken),
new JProperty("id_token", auth.IdToken));
await ServiceClient.LoginAsync(MobileServiceAuthenticationProvider.Google, jObject);
Any idea on the proper way to integrate this without having to write my own server-side token validation?
You would still need to configure the web application in Google since you are attempting to access a non-Google API. The native login on its own is not enough.
That means you will still need to provide the backend with an ID and secret. The client is responsible for obtaining an id token and authorization code which get sent to the server, and the server does the actual retrieval of the access token, per the Google documentation.
So that means your call will actually look something like the following:
var jObject = new JObject(
new JProperty("authorization_code", auth.ServerAuthCode), // not sure what property your auth binding exposes this as
new JProperty("id_token", auth.IdToken));
await ServiceClient.LoginAsync(MobileServiceAuthenticationProvider.Google, jObject);
There isn't documentation for the end-to-end using Xamarin.Android, but you might find it useful to glance over the App Service iOS documentation for this scenario just to see the moving parts. The general pattern you will follow is:
Configure everything for the server flow (as you've done before)
Set up the Google Sign-in SDK (seems like you've done that already, too).
Make the call as described above
The main issue you might run into is making sure that you have the API console registration correct. You'll want to make sure you have an Android client there connected to the web application client ID you are using. I'd recommend giving the Google Sign-in for Android setup instructions a quick look. Also note that authorization codes are one-time use, and there are some throttles that Google puts in place for a user requesting too many of them within some span of time. You might run into that during dev.
AS far as I know, the native client flow also use the google code flow to get access token.
According to this article, the Android, iOS, or Chrome applications doesn't need the secret to get the access token.
The client secret obtained from the API Console. This value is not needed for clients registered as Android, iOS, or Chrome applications.
But the web app backend will not authorized this access token if you don't set in your backend to enable Azure App Service authentication/authorization. Because the backend will have its own logic(the mobile server library write the logic according to the access token) to return the auth token according to the access token.
Now, the most easily way to enable the client flow in your mobile app is set in your backend to enable Azure App Service google authentication/authorization with the same clientid and secret(based on my test: if you don't set the right secret, the backend will still return the auth token).
Here is the test image:
If you still don't want to enable the app google easy auth, I suggest you could create custom authentication which contains your own logic to check the accesstoekn and get the user information from the google.
If the checked result is success and get the enough value, you could generate the auth token and return to the client side.
More details about how to create custom authentication in the mobile app backend , you could refer to this article.
For my current work project we're trying to use OAuth to secure a mobile API, but the app doesn't have user accounts, so authentication would take place invisibly from the user, where the app will send up some secrets to the server and receive the token to be used for subsequent web service calls. The problem is, all the libraries and tutorials I can find implementing OAuth follow this pattern:
Present a web view allowing a user to login
Receive a callback to a custom URL scheme, and parse the necessary information to authenticate future web service calls
How do I achieve this without the webview step? I should be able to make an HTTP request directly with the correct credentials which will return the necessary authentication details.
The app will use OAuth 2.0
It is not clear what do you mean by
the app doesn't have user accounts
If you want to call some API on behalf of user you should ask him for a password. Doing it in webview or not depends on provider implementation. For example, twitter doesn't force you to do that.
In other case, if you want to call service on behalf of client, take a look at this answer: https://stackoverflow.com/a/7477112/2283405
If the app doesn't require "personalised" or "user-specific" data to be manipulated, then you can probably try using "client-credentials" grant type to obtain access tokens using the application credentials granted upon the application registration process by the Authorisation Server (for e.g.: OAuth server) that's there in your environment. The idea is that, your app is what basically authenticates with the Authentication Server for you using the aforesaid credentials (i.e. Client Consumer Key and Client Secret Key).
NO, you have to do login compalsary. if you try without. it won't be possible.