How to submit prompt=consent via ueberauth_google - google-oauth

When a user has already given consent for an app (e.g. when a user abandons account creation during an initial attempt, then tries again), Google will not re-prompt for consent unless prompt=consent is passed (see documentation). Without prompting for consent, Google will not provide a refresh token to the calling server. And without a refresh token, the server cannot interact with the user's resources (e.g. sending email on the user's behalf).
ueberauth_google has a mechanism for setting approval_prompt, but this is a different parameter than prompt. Is there a way to send prompt=consent using ueberauth_google? (Note, if I add %26prompt%3Dconsent to the url that ueberauth_google sends me to, then Google does prompt me and our server does receive the refresh token.)

On your config.exs you need to add prompt: "consent"
config :ueberauth, Ueberauth,
providers: [
google:
{Ueberauth.Strategy.Google,
[
access_type: "offline",
prompt: "consent",
default_scope:
"https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtube.upload https://www.googleapis.com/auth/userinfo.profile"
]}
]
But this hasn't been merged to ueberauth_google yet. For the time being, you can go to your:
deps/ueberauth_google/lib/ueberauth/strategy/google.ex
And edit this line manually

Related

MSGraph Multi-Factor Authentication "interaction_required"

I'm using the Microsoft Graph login endpoint: login.microsoftonline.com/[tenantId]/oauth2/token with a grant type of "password" to log users in:
{
"grant_type": "password",
"client_id": "xxx",
"client_secret": "xxx",
"scope": "openid",
"resource": "https://graph.microsoft.com",
"username": "username",
"password": "********",
}
When I post this with users that are not enrolled in multi-factor authentication on our AD I get back the expected results including an access_token and refresh_token
However on users that are enrolled I get back a HttpStatusCode.BadRequest with an error of "interaction_required"
According to documentation from Microsoft found here:
In this case, your app receives a 400 with an interaction_required
error during access token acquisition or a 403 with
insufficient_claims error when calling Microsoft Graph. In both cases,
the error response contains additional information that can be
presented to the authorize endpoint to challenge the user for
additional information (like multi-factor authentication or device
enrollment).
However I do not see any additional information in the results and can't find much information on next steps. The JSON I get back looks like this:
{
"error":"interaction_required",
"error_description":"AADSTS50079: Due to a configuration change made by your administrator, or because you moved to a new location, you must enroll in multi-factor authentication to access '00000003-0000-0000-c000-000000000000'.\r\nTrace ID: aee10c85-fd12-42ec-be6c-76d546500100\r\nCorrelation ID: 0ee3ebac-f702-4fbc-be76-fd6a291ad488\r\nTimestamp: 2021-09-09 17:45:24Z",
"error_codes":[50079],"timestamp":"2021-09-09 17:45:24Z",
"trace_id":"aee10c85-fd12-42ec-be6c-76d546500100",
"correlation_id":"0ee3ebac-f702-4fbc-be76-fd6a291ad488",
"error_uri":"https://login.microsoftonline.com/error?code=50079",
"suberror":"basic_action"
}
But I am getting back "interaction_required" and confirmed with our AD administrator that they are definitely enrolled. So I am at a bit of a loss for next steps to resolve this.
Cause :User is attempting a authentication method that requires Multi-factor authentication
Try to catch the error you get, and perform a new request according to steps for your flow scenarios by referring from this MS docs
Microsoft Graph has special considerations when building apps in
Conditional Access environments. Since Conditional Access policies are
assigned the specific datasets, Azure AD will enforce Conditional
Access policies based on the data behind Graph - rather than Graph
itself.
(or check below points)
Conditional access policies prevent non-interactive flows to work.
Possible solutions...
Use a interactive flow instead.
If you are using a interactive flow and still getting this error, please make sure openid is one of the scopes during the interactive sign-in. You might be getting the error after the interactive sign-in and trying to exchange the authorization code for a access token...
Example:
https://login.microsoftonline.com/contoso.onmicrosoft.com/oauth2/authorize?client_id=#...#
&response_type=code
&scope=openid groups.read.all
&nonce=1234
&redirect_uri=https://app.contoso.com
Notice "scope=openid groups.read.all" in the request above
Add the client application to the exception list of the Conditional Access Policy
Add the user to the exception list of the Conditional Access Policy
If you are not using conditional access policies and the user is directly enabled for MFA, then as a last thing, disable MFA for the user if solutions above do not work for you.
Or you can use certificate based authentication instead of MFA
References:
login-to-azure-web-application-fails-with-aadsts50079
SO thread

Expo: WebBrowser.openAuthSessionAsync and related calls skip user input even when browser session expired

This is a summary of an issue I filed directly with expo (it ws closed but I have asked for it to be reopened):
This issue happens whether using AuthSession.startAsync,
AppAuth.authAsync or WebBrowser.openAuthSessionAsync on iOS in
local development and published release (expo managed). Haven't tried
on standalone build yet.
Steps to Reproduce
user presses 'sign in' button, (app calls one of the above methods to kick start authentication session with a Salesforce oauth provider)
user enters credentials successfully
app goes through oauth redirects and returns user to our app and we get our access token.
user presses 'sign out' button (app calls revoke endpoint for token, then calls server endpoint to delete any browser cookie sessions for given account reference)
app navigates to sign in screen
user presses 'sign in' again (app calls the same method from above to start the authentication session with Salesforce oauth provider again)
instead of opening the sign in page, the app redirects itself back with an access token as if the user had successfully entered their credentials, even though any cookies/session data the browser stores should be invalid and necessitate a sign in.
Expected Behaviour
steps 1 - 5 are all as expected. Step six should be
app redirects to Salesforce oauth provider sign in page, in unauthenticated state (ie no cookie or session data that was previously stored is still valid)
user is required to re-enter their credentials
oauth flow takes over and redirects the user into the app if the credentials were correct.
Actual Behavior
as per initial steps where the user is not even asked to enter their credentials (step 6):
instead of opening the sign in page, the app redirects itself back with an access token as if the user had successfully entered their credentials, even though any cookies/session data the browser stores should be invalid and necessitate a sign in.
Reproducible Demo
The code is in a private repo so I can't share details of it, but it's a very standard oauth flow, and seeing it's happening in all three of the method calls from the top suggests to me that it may be due to something in the WebBrowser.openAuthSessionAsync implementation. I have seen on the apple developer docs that SFAuthenticationSession has been deprecated in favour of ASWebAuthenticationSession. My understanding is that this (SFAuthenticationSession) is the browser used by expo's WebBrowser and the wrappers mentioned above (AppAuth and AuthSession) for the oauth interactions. I also see that it mentions it's for a one-time login, which perhaps explains why it would hold onto any session data and jump to the conclusion of re-authenticating without directly seeking credentials from the user, but it seems unhelpful to store a cookie without validating it, which is what appears to be the end result.
Notes
Essentially this is making it impossible for a user to sign out of our app, because the system browser, that we don't have control over, is keeping track of their authentication despite the session value no longer being valid against the server.
I've seen other people looking to find ways to clear cookies from the system browser, which may be what this issue relates to, though it doesn't appear to be possible to access the auth session's browser cookies in any way. This comment on a GitHub issue is exactly what I'm experiencing and need to find a solution to.
I would like users to be able to sign out, and then when they sign back in again they should have to enter their credentials again. Does anyone have any thoughts as to how this might be possible?
On iOS, it's now possible to pass in the following config to WebBrowser.openAuthSessionAsync to essentially treat it as incognito and ensure it doesn't retain any cookies. The effect is that the user will have to re-authenticate each time (even if there session is still active). I'm not aware of a similar approach for Android, however.
Code
const browserOptions = {
preferEphemeralSession: true
}
result = await WebBrowser.openAuthSessionAsync(authUrl, redirect, browserOptions)

Auth0 asks for consent to access tenent when logging in

I am developing an Angular2 app which uses auth0 for authentication. I used the auth0 lock widget to authenticate users.
Now, I want to use auth0-js instead of the lock widget for authentication. I followed this guide to add auth0-js to the app.
After adding auth-js, when a new user tries to log in to the app, Auth0 displays following consent screen to the user.
I want the users to be able to directly access my app, without needing to accept a consent screen. The consent question asked in this dialog can be confusing to users since it mentions about tenants.
When I searched for a solution, the solution mentioned in various places was to make the client a first party client. But, I cannot find any place in the management console to make the client a first party client.
How can I disable this consent screen?
Following is the auth-js config I used in the app.
auth0 = new auth0.WebAuth({
clientID: 'my_client_id',
domain: 'my_domain.auth0.com',
responseType: 'token id_token',
audience: 'https://my_domain.auth0.com/userinfo',
redirectUri: window.location.origin + '/auth_loading',
scope: 'openid'
});
In Auth0 Dashboard, under APIs -> Auth0 Management API -> Settings (tab)
If you are using a specific audience for a Resource API you have defined yourself in the Dashboard, then there is a similar Allow Skipping User Consent toggle for that particuar API. Use that. audience specifies the target API for your access token. If you don't want to call a specific API, keep it set to https://my_domain.auth0.com/userinfo
Re. question about First Party. If you created your client in the Auth0 Dashboard, then it is Firsty Party by default. Only first-party clients can skip the consent dialog, assuming the resource server they are trying to access on behalf of the user has the "Allow Skipping User Consent" option enabled. The Auth0 Dashboard does not offer a flag for this, but if you use the Auth0 Management API v2 Get Clients endpoint, then you will see the flag (boolean) value listed for your client eg.
"is_first_party": true
See https://auth0.com/docs/api/management/v2#!/Clients/get_clients for details.
Finally, please note the following: https://auth0.com/docs/api-auth/user-consent#skipping-consent-for-first-party-clients - in particular note that consent cannot be skipped on localhost. As per the docs (link above), During development, you can work around this by modifying your /etc/hosts file (which is supported on Windows as well as Unix-based OS's) to add an entry such as the following:
127.0.0.1 myapp.dev

Sign in as a different Box user

I am trying to integrate my iPad app with Box. I am having an issue with the Box API where files in the account of one user are returned for some other user. Here are the steps to reproduce this issue:
Make the authorization calls and get the access token as mentioned in this guide. For login, I am opening the Box login page in Safari. I have the specified a custom url scheme for the redirect url, which opens up my app after the user logs in.
Once you get the access token, make a call to list the contents of the root folder. This succeeds.
Delete the app from the iPad and rebuild it.
Again go to the login process (as in step 1), but this time use a different Box account to login. You get a new access code and OAuth token this time.
If you make the call to list the files using the new token, you will get the response from the earlier account. Ideally it should return the files for the currently authorized user.
Does Box use just OAuth to return response or does it use cookies as well? Because after authentication and receiving the access token, I also see a cookie from Box (verified using [[NSHTTPCookieStorage sharedStorage] cookies]).
I have tried repeating the above process by deleting all Box cookies before starting the authentication flow. Also, I am not saving the OAuth token on disk and retrieving it. I am not saving/caching the response in any way.
One more thing that I have noticed is that there can be two Box users logged in at once in Safari. Also, if I make the authentication request, get the access token and again make the authentication request, it shows the login page again (instead of showing the allow/deny access page). Is this intentional?
I am using the Box v2 API and iOS 5/6
Upon further inspection, the problem seems to be with Box servers caching response. I did a quick test with curl using two different access tokens created from the iPad app. I made a call to fetch the user files for the root folder using both tokens. The results were correct, i.e. I got the correct files for each account.
When I did the same test on the iPad app, the files for one user were returned for the other user. If I maintained a considerable gap between the two logins, I got the correct files.
To permanently fix this, I am setting the Cache-Control header to no-cache for the request to fetch the user's files.
But it is strange that I have to do this. Box needs to check their cache validation logic IMHO.

j_security_check is not available if user is already logged in

Apache tomcat version: 6.0.20
If user is already logged, and he tries to login again from login page, the j_security_check is not available error is encountered. Is it normal behaviour or I have to do something?
Actually I have different user roles for accessing different pages, and when access to a page is denied to a particular user, I want to redirect him to login page, where he can login with corresponding credentials.
This behavior is normal: the servlet spec only lays-out the procedure for container-managed authentication (i.e. login) when the user requests a protected resource and the user has not already provided credentials. All other scenarios are left undefined, including yours.
If you want to capture "forbidden" conditions, you can use <error-page> mappings in your WEB-INF/web.xml to send the user anywhere you want, including a login page. Just remember that the container will only accept a login after the above conditions are true, so you may have to log the user out first (by terminating the user's session).
What I might recommend is a "forbidden" page that says "You don't have access to this resource. If you'd like to log-in as a different user to access it, please click [HERE]" where [HERE] is a link to a servlet that terminates the user's session and then redirects to the resource the user was trying to access. This will cause the container to request authentication (i.e. present the login form), verify the credentials, and send the user to the desired resource.
If you are using a container (and webapp) along with version 3.0 of the servlet specification, there is a new HttpServletRequest.login() method that can be used to programmatically log a user into your webapp. You might be able to use that instead of terminating the session and doing all those redirects... instead, you could collect the username and password yourself and then ask the container to do the login for you.