"'openid profile offline_access' is not valid" error when calling acquireToken method with code - msal

I am using Authorization Code Flow. I want to get consent for two different audience/resource in one login popup.
So, I know that it is needed for acquireToken for first audience and then acquireTokenSilently for second audience.
However I got below error when calling acquireToken method:
AADSTS28002: Provided value for the input parameter scope 'openid
profile offline_access' is not valid when requesting an access token.
Please specify a valid scope.
I remember that I didn't get this error when I tried this scenario last week.
Also, I didn't add the openid, profile, offline_access scopes, it is added to url automatically by the library.
Then below url is generated.
https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize?scope=openid+profile+offline_access+https%3A%2F%2Fgraph.microsoft.com%2FUser.ReadWrite.All+https%3A%2F%2Fteamsconfigapi-int.trafficmanager.net%2Fuser_impersonation&response_type=code&redirect_uri=https%3A%2F%2Flocalhost%3A8080%2Flogin&state=bd237c04-76b6-4a76-beca-fe4650c1f64d&nonce=3eab6371-df43-5cga-aded-a106fed74ab6&prompt=consent&client_id=56b7k4bh-8ce4-4b45-adkd-c51cdf5t52c2&response_mode=query
Note: Also, when I getting https://graph.microsoft.com/User.ReadWrite.All and https://teamsconfigapi-int.trafficmanager.net/user_impersonation consents separately(in two different login popup), there is no any problem. I can get AuthenticationResult objects both of them.
Why I got this error?

You want to collect consent from two separate audiences/resources in one login popup, however you cannot get an access token for scopes that span more than one resource. You will need to request two access tokens for two different resources. The first can be accomplished using loginPopup, and the second can be accomplished using acquireTokenPopup or acquireTokenSilent.
Read more here: https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/resources-and-scopes.md

Related

Login via hooks

I'm currently developing an application where holders can see historical data of their NFT's. All code is in place, but I'm still looking for a way to securely verify their ownership of a certain NFT.
There is the possibility to extend one of the dApp examples in the Elrond docs, but I'm not that familiair to React or NodeJS, so I'm trying to build this in PHP.
One thing I came across, is the login via Hooks, as used by the Maiar Exchange.
https://docs.elrond.com/wallet/webhooks/#login-hook
However, the Callback URL can be accessed manually by users, so this can give people Unauthorized access to my application.
Now, there is an undocumented extra parameter token I can pass to the Login hook (as used by Maiar Exchange). I know I can fetch a valid token by sending a POST request to 'https://id.maiar.com/api/v1/login/init'. This will give back a token I can append to the Callback URL. By doing so, the Callback URL will receive an appended signature parameter. I feel like I'm almost there, but the question is: How can I interpret this signature and how can I use this signature to verify if the returned response was valid and belongs to the given token/address? How was this signature is generated?
Also, I feel like it would be very nice if there was some sort of OAuth implementation for Elrond, but since it isn't there, I'm trying this approach.

Outlook IMAP scopes giving an AUTHENTICATE failure with new MS Graph API

I'm requesting the following scopes (URL encoded):
offline_access user.read https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/SMTP.Send
The authorization process with OAuth 2.0 using the new Microsoft Graph API seems to work fine, but when using the access token to connect to IMAP over XOAuth2, I'm getting a NO AUTHENTICATE, which indicates the token is invalid.
It turns out this is not an issue with the user but rather with Microsoft's Graph API. Although it is not documented, you are currently not allowed to request a token with a scope that falls under two tenants, or it will choose one and fail silently.
In this case, User.Read falls under Microsoft Graph tenancy. Technically speaking, if your user is an organizational Outlook/Office365 user, they likely don't actually have Microsoft Graph installed and the correct scope would be https://outlook.office.com/User.Read. However the Outlook profile endpoint has been deprecated and would be unadvisable to use (you also have no way of knowing whether or not your user has MS Graph tenancy). It seems to resolve this, the user.read permission can be requested without specifying the Microsoft Graph URL.
This is essentially what you are doing above, but can be misleading as you are not actually requesting the general User.Read permission that can then be resolved to the Outlook tenant. What is actually happening is that User.Read permission is being mapped to some default tenant, and so your scopes actually contain multiple tenants (both the default tenant and Outlook).
Since this is not allowed, it fails silently and defaults to the default tenant. With most of their APIs this still works, but specifically with IMAP/SMTP you cannot request a larger scope/multi-tenant key or it will not validate over XOAuth2. You will note that the access tokens returned for IMAP/SMTP alone are always much smaller than the access tokens for other scopes.
To remedy this, you will need to request two access tokens. Firstly, you should use your authorization code to request a key within the following scope:
offline_access https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/SMTP.Send
Following this, you need to request an access token for the profile. However, as of October 2020, you are no longer allowed to use a single authorization code for multiple access token grants. So you will need to login the user once more -- the canonical way of doing this is to simply navigate them back to the auth URL, leaving the login_hint field empty. This will vary depending on how you are constructing your URL, but here is an example in JS:
url = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize?'
url += `client_id=${clientId}`
url += '&response_type=code'
url += '&redirect_uri=${redirectURI}'
url += '&response_mode=query'
url += '&login_hint='
url += '&scope=offline_access%20User.Read%20https%3A%2F%2Foutlook.office.com%2FIMAP.AccessAsUser.All%20https%3A%2F%2Foutlook.office.com%2FSMTP.Send'
url += '&state=12345
Note that your authorization code must request the full scope (including both User.Read and IMAP scopes like IMAP.AccessAsUser.All, for both access token requests. Specifying a smaller scope will not guarantee that the profile you read will necessarily correspond to the Outlook account.
After receiving this second authorization code (it won't ask the user to login manually again, just load a bit and automatically resolve a second code) you can request a new access token with the following scope:
user.read
You can include any other Graph API scopes above, but specifying something under Outlook and especially under IMAP will mix up your scopes. The response scope will still contain EAS access and Outlook scopes, but with the addition of the user.read permission.
You should use this second token to access the profile and refresh it separately from the first token (which should only be used for IMAP/SMTP).

Onedrive OAuth 2.0 code flow for getting access token 'redirect uri' is not specified in the list of urls specified

Before adding, yes it works when I give the entire url like http://localhost:8080/onedrive/oauth2/success/1 in the list of uri in azure uris. I am using code flow to authroize these tokens.
But as per the docs, it should work with me just mentioning the domain name there, like http://localhost:8080. Which it doesn't.
I want to do something like send the user id along with every request for me to keep track of which user I should link this accees token to, and have no idea to do so, if this issue is there. My current application logic is, when my application sends the user details and calls my spring API, I want to handle all these transfer of tokens in the server side, so I want to transfer this userId as my path variable. How do I go about doing this? Has anyone done this, can they explain to me any other different solution?
You can't add custom details to OAuth redirects and it is best practice to always register the full redirect uri.
In terms of tracking the user, after login the token has a user id and you can also get fields such as user name and email - so both the UI and API will know which user each token is for. I can provide further details on mechanics if needed.
The user id in a token is often a generated value, whereas the user id you want to use in API path segments is maybe a user id from your app's back end database - if so you will need to map between token details and database details.
If you provide redirect uri as http://localhost:8080/ then it means you are handling the api response in
/
endpoint and not
/onedrive/oauth2/success/1
To get to know the user to whom you are linking, few ideas which you can use are
1) Use security to obtain the logged in user credentials (Ex: Principal if you're using Spring security in java)
2) After successful authentication, use the user id you have and send one more request to backend and store it database with userid as a key

How to add multiple redirect URIs for Google OAuth 2?

I am trying to make Google OAuth 2 authentication work with a toy app I am running on my computer (at localhost:8080) using Social Auth for Java.
However when my app connects to Google to authenticate the user, Google responds with this error page:
My app, named "My Hobby App", is configured in the Developer Console as such:
In the Google OAuth 2 docs, it is specified that:
redirect_uri: One of the redirect_uri values listed for this project
in the Developers Console.
Determines where the response is sent. The
value of this parameter must exactly match one of the values listed
for this project in the Google Developers Console (including the http
or https scheme, case, and trailing '/').
I have a couple of questions:
How can I add multiple redirect_uris to my app?
Why is Google identifying my app as "Project Default Service Account" rather than "My Hobby App"?
It's actually easier than you think, unfortunately, it took me a couple of hours to figure it out.
How can I add multiple redirect_uris to my app?
Normally when you add multiple links to something on Google or elsewhere you separate it by , or ; but with Redirect URIs you have to use a new line, it's actually not very intuitive. So when you press the Edit Settings button, you can add to the URI and/or Origins if you have a couple more links, separated by newlines (enter).
No need for complicated app configurations or new keys.
Why is Google identifying my app as "Project Default Service Account" rather than "My Hobby App"?
On your second question: You have to go to the "Consent Screen" tab to change your app info such as your PRODUCT NAME, HOMEPAGE, LOGO, etc.
This answer may not be an exact answer to the question, but I think this might help those who are using Google OAuth for the first time and are wondering why their multiple URIs are not being recognized.
We use the redirect URI at 2 places in the code. First time, while fetching the auth code and a second time, when exchanging this code for an access token.
In the Google docs, it is clearly mentioned that the response for the auth code request(1st request) will be sent to the redirect URI. So, if you make the request from an endpoint A and specify the rediredt URI as endpoint B, Google will send the auth code to endpoint B. This is clear and worked fine without any errors.
Coming to the second request, the documentation is somewhat ambiguous. The redirect_URI parameter is described as below:
redirect_uri: The URI that you specify in the API Console, as described
in Set a redirect URI.
This is where I made a mistake in understanding how this works. Following a similar approach to the first call, I used a third endpoint C and passed this endpoint C in the redirect_URI parameter while making the second call. I got a URI mismatch error although my endpoints B and C are specified in the API console.
The problem is that, unlike in the case of first call, the response to the second call comes to the same endpoint from where the request is made. I made a request in python like below:
r = requests.post(token_endpoint, params)
r has the response with the token.
I was getting a URI mismatch because, I am supposed to use the same redirect_URI in both the calls.
So, for a single OAuth request, we need to use a single redirect_URI.
But then, that brings up the question, why are multiple redirect_URIs allowed in the API console for a single app. I am assuming that if we need to make multiple pairs of authCode-token calls in the same app, we have the leeway of using multiple redirect_URIs.

oauth/initiate says page not found

I am not able to get a request token from the oauth/initiate page because it says page not found. What could be the problem?
I have created an oAuth customer, given the appropriate REST roles and attributes. Also, appended the consumer key, secret, nonce etc. in the authorization for the oAuth request.
What am I missing?
Oauth will give you page not found if the request params are incorrect. It's likely your client isn't sending the parameters correctly, or your signature doesn't match the one Magento is calculating.
I added some temporary logging to the OAuth server to try and track down the issue.
Add this to file app/code/core/Mage/Oauth/Model/Server.php after line 594, it will help you see what specific oauth error is being raised
Mage::log($response, Zend_Log::DEBUG, 'oauth.log');
Try your initiate request again, and then check var/log/oauth.log to see what the error is.
Don't even think about doing this on a production system, and ensure you roll back your changes afterwards. You should never modify core files other than for temporary debugging.

Resources