We have two Azure AD Web Apps Registered under one outlook account for OneDrive Development under the portal apps.dev.microsoft.com . We have created two apps because we need our app to support callback URLs from two servers with different DNS. Unfortunately only the first app that was created works in which we can get the access token using V2.0 end point and then subsequently can access One Drive Resources using graph API.
The second App that we created to supported another server with a different DNS does not work. We are unable to get access token and the response is below,
AADSTS70000: The request was denied because one or more scopes requested are unauthorized or expired. The user must first sign in and grant the client application access to the requested scope
One App: reply URLs: https://www.example.org/OneDriveApp/callback.jsp - works great
Second App: reply URL https://www.example2.net/OneDriveApp/callback.jsp - failure to get OAuth Access Token.
This error generally means the auth code you've gotten is not meant for tokens on the specified endpoint. This can happen from misconfiguring the auth endpoints, registering the app in the wrong spot, or a malformed request.
The first thing to check with this error is your auth endpoints.
Next, make sure you're using the correct library to obtain the authorization code.
Also, make sure that you are not registering the app in the wrong blade (regular AD vs b2c).
What do you have as the URL for the token endpoint?
Related
Cant establish persistent API connection to GA4 from Make (formerly Integromat). I use an HTTP OAuth 2.0 connection
I've enabled the Google Analytics Data API v1
In GCS I've created a project, Enabled the above mentioned API with authorized domains integromat.com and make.com and also created an OAuth 2.0 app. The scopes I added was:
https://www.googleapis.com/auth/analytics.readonly
https://www.googleapis.com/auth/analytics
I created credentials for a web app with the Authorized redirect URI’s of
https://www.integromat.com/oauth/cb/oauth2
https://www.integromat.com/oauth/cb/google/
The connection works but only for a short period (I assume the token expires). To try and mitigate this I created a service account. That does not work as I cant find a way to add an authorised URI to a service account. This is the Make error:
Error 400: redirect_uri_mismatch
You can’t sign in to this app because it doesn’t comply with Google’s OAuth 2.0 policy.
If you’re the app developer, register the redirect URI in the Google Cloud Console.
Request details: redirect_uri=https://www.integromat.com/oauth/cb/oauth2
Any ideas please? I’m truly stuck
Your question lacks a bit of information as to what it is exactly you are trying to do. However there is enough here that I can help you clear up a few issues or miss understandings.
Oauth2
Oauth2 allows your application to prompt a user to request permission to access their data. The authorizaton server returns to you an access token, this access token is good for only an hour and then it will expire.
If you are using a server sided programming language then you can request offline access, at which point the authorizaiotn server will return to you an access token and a refresh token. The refresh token can then be used by you when needed to request a new access token.
service accounts.
Service accounts can be used if you are only accessing private data that you the developer own. You can create a service account, then go in the admin section of the google analytics website and add the service account as a user it will then have access to that account. There will be no need to request consent of a user to access the data it will just work. Note: service accounts only work with server sided programming languages.
redirect uri issue.
The redirect uri must exactly match the web page that your application is sending. In this case the error messages says you are missing https://www.integromat.com/oauth/cb/oauth2 you should add that.
Google OAuth2: How the fix redirect_uri_mismatch error. Part 2 server sided web applications.
I've been reading through a bunch of documentation for using OAuth with Azure AD, but am still completely confused about how to properly implement things for my situation. Hopefully someone can steer me in the right direction.
I have created an ASP.NET Web API application that uses the EWS Managed API to access Exchange on behalf of different users. My application exposes endpoints such as /Mailbox/Messages and /Appointments with the intent that some front end web application will eventually use them to retrieve a user's emails and appointments. Currently the endpoints are working using basic http authentication, but I'd like to update them to use OAuth. The application has been registered in my Azure AD instance and I've configured it to require the "Access mailboxes as the signed-in user via Exchange Web Services" API permission.
Since the front end hasn't been implemented yet, I've been trying to test by manually calling the authentication endpoint. This prompts me to log in and provide consent. If I consent, I'm redirected to the callback URL that I provided when I registered the app with the authorization code contained in the query parameters. I'm still not quite sure how I'm supposed to be using this callback, but for the sake of testing I currently have the callback redeem the authorization code for an access token. This is done by calling the AcquireTokenByAuthorizationCode method on an instance of the AuthenticationContext class and providing my application's id and secret. Again, just for the sake of testing I return the access token to the browser. I can then call my aforementioned endpoints (after some modifications) with this access token and get the emails for the user. I'm guessing much of this is not the correct way to be doing things.
Some of my points of confusion:
What should the callback that I registered in Azure AD actually be doing when it gets the authorization code? Is this intended for a different type of application? Perhaps one that isn't just playing the role of a middle man.
I'm trying to make my application somewhat RESTful, so I don't want to have to maintain the access tokens on my end between requests. As such, does it make sense for my endpoints to expect that the access token be provided in the authentication header for each request? If so, does that mean the front end application should be responsible acquiring the access token and passing it to me?
Being completely new to OAuth and Azure, I'm not sure if any other details are pertinent, but I can provide more information as needed.
What you are implementing is this scenario: https://learn.microsoft.com/en-us/azure/active-directory/active-directory-authentication-scenarios#daemon-or-server-application-to-web-api
Here's how it works:
Your client app redirects the user to sign in at the authorization endpoint
Your client app gets back an authorization code (if using the auth code grant flow, there are others)
The client app exchanges the code for an access token for your API app
It will need to provide its client id and secret along with the code and the API's resource URI to get it
The client app calls to your API app, passing the access token in the Authorization header
Your API app then validates the access token, and requests for another access token from Azure AD for the Exchange API
It will pass the access token sent by the client app, along with its client id and secret and the Exchange API's resource URI to Azure AD
Your API app receives an access token so you can call to the Exchange API as the user
And to answer your two questions:
Authorization code flow is not used with APIs, only with apps that have a user signing in, thus the redirect URL is basically never used
Your API can and must expect and authenticate the access token for it to be in every request. But the access token it uses to call the Exchange API can and should be cached on the API's side. This is provided out-of-the-box with ADAL, though the tokens are only in memory.
I'm following the guide and example provided by Microsoft here and I'm able to get the demo working, with the authentication happening in a console app, then making a request to a Web API with the correct token.
I'm looking to use this but the code in the console app would need to move to a Web App. Essentially: external server tries to access secure Web API, providing Azure AD username/password in the Authentication header of a HTTPS request. I pick up these credentials in the first insecure Web API, and attempt to authenticate the credentials against AD, obtaining the token. From here, I would then call the [Authorize]-protected Web API by making a request with the AD token.
At this point I'm using the same code from the example linked above, simply moving the code in the Console app up into the first insecure Web API controller, but I'm having no luck. I read on CloudIdentity that "You can only use those flows from a native client. A confidential client, such as a web site, cannot use direct user credentials.". Is this true? If so, is there another way to achieve my aim? I need to use the credentials as it may be likely that more services would use the API in the future, so each of these would need their own credentials to use that could be managed within Azure.
EDIT: In reading more around this, should I actually be aiming to use Client authentication, creating an "Application" within the Azure AD, and providing the client ID to each external service looking to call the API, to then authenticate with that, rather than credentials?
Yes, your edit is correct. The Resource Owner Password Credentials grant is meant to authenticate users, not applications. Typical use would be from an application that prompts you for username and password and then retrieves a token from Azure AD.
You can use the Client Credentials grant to get a token from Azure AD from a confidential client to call an API without user context. This flow requires that you register the application in Azure AD and generate a key (which will be used as the client secret). You can then use the ADAL library to ge a token from AAD as shown here.
Background
I want to create a PHP application that eventually will be installed on a "countless" web servers.
The application is going to access the Google Drive associated with the web server's administrator Google account (it will basically write some files on user's cloud storage). So my PHP app will be authorized by the end-user to use its Google Drive storage. This is done (via the OAuth2 protocol) by connecting the Google OAuth2 service.
So basically I have to create a ClientID/Secret pair (on behalf of my Google Account) that is gonna be used to execute the authorization flow.
Google provides 3 authorization methods:
for web applications (web browsers over network)
for service account (my server to Google server)
for installed application (like Android, IPhone)
(1) is perhaps the best choice EXCEPT that I have to define a REDIRECT_URI where the authorization code will be sent. Because my APP will be installed on a "countless" different servers I don't know in advance the protocol, domain name and the path (also the URI) where the Google's response should be returned. If I would install this application only on 3 servers I could create upfront a ClientID/Secret pair for each of them. It's not the case.
(2) means to deploy my P12 private key with the PHP application and I don't feel comfortable with that!
(3) means to put the end-user to copy/paste an authorization token from a Google web page into my application web interface. I am trying to avoid doing that.
I already made it to work by using the method 1 when I know in advance the REDIRECT_URI. I also embedded the client_id/secret pair in the source code so the whole authorization process is user-friendly. But this is not going to work on a "countless" deployment scenario.
Questions
Which method and how should I use it in order to make the whole process safe for me (as developer) and for the client too (the web server administrator). Note that the authorization process should not involve the end-user to copy paste some codes. I want that step to be transparent/user-friendly for the end-user (no one likes copy-paste when it can be done automatically).
Should I embed my client_id/secret into the application or that's totally wrong? I suppose no end-user wants to go through the creation of its own ClientID in Google Developer Console, right? On the other hand why I would give my client_id/secret to an unknown end-user?
Final thoughts
I could create a proxy application on my (the developer) web server such that my PHP application (which is supposed to be deployed "everywhere") will send the authorization request to my proxy server (which has already its own client_id/secret) which in turn will redirect the call to the Google OAuth service which then REDIRECT_URI back the authorization code to my proxy and finally I will redirect back the response to the original sender (the PHP application). What do you think?
Some useful answers here and here or here.
#Edit: as I've already said earlier a proxy would be a solution. I've made it and it works. The same solutions I've received also from user pinoyyid. Thanks for your answer too.
A proxy is the only real option open to you. You can encode the originator URL in the "state" parameter, so that when the proxy receives the access token, it can call a webhook at the originator.
There are some contradictions in your question...
"The application is going to access the Google Drive associated with the web server's administrator Google account" and "So my PHP app will be authorized by the end-user to use its Google Drive storage." are mutually exclusive.
If the Drive storage belongs to the app, then the user isn't involved in any OAuth dialogue.
Could you edit your question to be clear who is the owner of the Drive storage as it greatly influences the OAuth flows.
I know there has to be an obvious solution to this problem and I am missing it, so I would much appreciate someone enlightening me so I don't spin my wheels...
I am writing an ASP.Net application that will interact with a service API (Evernote specifically). Evernote requires OAuth for security and before I can actually interact with the objects I need to obtain a token.
The workflow goes like this (explaining it to myself as much as anyone else!):
Build a url with my development api key and secret key and some other OAuth stuff, send it to Evernote to request an access token.
Send the url as a request to Evernote and pull the new access token out of the response
Build another url with the access token to request an authentication token for the user. This url goes to a page the user must interact with to login (if they haven't already) and then authorize my application to access their account. The last param of the url I build is a callback url which will be called from Evernote's servers.
If all goes well, Evernote will request the callback url and include the new authentication token as a param.
Once my server receives the callback with the embedded token I can use it so that my app can interact with the users' notes on subsequent requests.
The problem is that I'm writing this app on a local box, not an ISP under a public domain. So my callback is to the localhost server. Of course, localhost is relative, so Evernote can't resolve my callback... I can't ever receive an authentication token and debug at the same time.
There has to be a way around this problem because this authentication model is not unique to Evernote (by a longshot... Flickr uses it as do a lot of other services). So can someone tell me how to set things up so I can get the authentication token and still be able to debug on my local box?
Help is much appreciated!
OAuth is quite tough to implement. It may not be the answer you're looking for, but this is how I managed to get the job done:
Write some code on my local dev machine.
Run a bat file (or alternatively hook a post-build event in VS) that executes a msbuild deploy script and deploys the application to a test server.
Run the application on the test server. After obtaining the request token and requesting for authorization it redirects to the Evernote website.
After successful authorization the Evernote website redirects back to my test server and the authorized request token is exchanged for an access token.
Instead of debugging (I don't have VS on the test server) I examine the logs of the application (the logging I used was as simple as writing to a text file).
Rinse and repeat
For the purposes of testing I registered a temporary public subdomain (e.g. testing.oauth.mydomain.com) so that Evernote will be able redirect to that url.
According to this (How do I develop against OAuth locally?) the callback is issued by the browser, so it should be able to hit localhost.