I am using ADFS 4.0 for authenticating into my mobile application using OpenId Connect / OAuth2 flow. Basically when I sign in to my application, my mobile appliaction opens a browser to start the flow. Whenever I sign out from the application, I need to fire the ADFS sign out page to clear the cookies and redirect back to the application.
The problem I have is that when I successfully authenticate through ADFS, I need to perform some user validation in my API for the user which sometimes can fail. If the validation fails, the session cookies stays in the mobile devices browser, so the user is not prompted for credentials anymore, so hes stuck in a loop where he cannot sign in to the application again. I really don't even need the session cookies stored into the mobile devices browser because I am using the access and refresh tokens to handle the flow after the authentication.
I have configurated my application as native application / Web API in ADFS. Is there any way I could disable the cookies to be saved in the mobile devices browser or is there any other approaches for this problem?
Are you using authorization code grant flow?
If yes, you can use prompt parameter in authorization request. As explaining in this document about prompt , with prompt=select_account, user will be forced to choose current signing account or choose to login in another account, or with prompt=login, user has to reauthentication...With those values of prompt, you will not be "stuck in a loop where he cannot sign in to the application again"
Related
I am using Django 2.2 for my webapp.
And I have been looking for tutorials that cater for QR code cross login to webapp using mobile app.
Basically the workflow is like this:
expected workflow
User arrives at website on desktop
Given a choice of username/password or QR code login (We assume user is registered)
User chooses QR code to login
User is prompted to install mobile app (can be android or iOS)
User installs mobile app and logins using username/password.
On mobile app, user then agrees to future login using QR code as alternative (this is done once)
After this, in future logins, when User chooses QR code to login as per step 3. They use the mobile app to scan QR code generated on the website login page.
The mobile app then uses FaceID or FingerPrint ID (assuming iOS) to then allow login. The user presses a Yes button on the mobile app to confirm login.
Somehow the webapp is notified dynamically and allows login on the desktop browser.
I don't quite get how the mobile and the web app at the backend all work with one another to achieve this seamlessly.
What I did find
I did find this library https://github.com/aruseni/django-qrauth which seems no longer maintained. But I still cannot quite get how the flow works between mobile app and webapp backend.
I also found this https://medium.com/#ksarthak4ever/django-two-factor-authentication-2ece42748610 which seems to use the mobile phone as a 2FA device. Not exactly the use case I am looking for unless I misunderstood.
I did find this article https://backendless.com/how-to-implement-mobile-to-web-cross-login-using-a-qr-code/ which is what gave me the term "cross login". However, the article is tilted heavily towards this particular vendor.
I am looking for an "understanding" of the concept without being reliant on the specifics of the vendor implementation.
What I am not looking for
In case, my question is poorly phrased and gets misunderstood, I have included this section to make clear what I am not looking for.
I am not looking for the use case where the QR code serves as a 2FA confirmation for the authenticator app.
I am also not looking at code examples yet. I just want a clear understanding first of how things work between the mobile and web app. I believe JWT is needed though I am guessing.
A workflow is more appreciated than actual code because I want to gain an understanding first of how this works.
The key concept is that login occurs when a user and browser are matched. A user means a user(or a user device) already recognized(authenticated) by the server.
user's PC browser requests QR login to server (without any account information)
server makes login request key and send the key to the user's browser. the key is displayed as QR code. (the role of this key is to identify the browser)
user's already logged-in device(user) read the key(QR) and sends a login acceptance request to the server with the key.
At this point, the server knows who both the user and the browser are.
The server allows the browser to log in as the user.
The key to identify browser could be session or web socket channel or any other form of information.
The server must store the key until the login process is complete.
If a valid login acceptance request is received, the server should prompt the browser to log in.(server->client, push). there are several techniques for accomplishing this.(polling via AJAX, Web socket, push notification services, etc..)
I'll explain it with Django-channels web socket framework. (In this case login request key and channel name is same. but different key and channel name is also okay.)
browser: user chooses QR login. (without any account information)
Backend: web socket channel is made. name of the channel is securely randomly generated string(FOO). key(FOO) is stored in redis as Django-channels[redis] made a channel named that string(FOO). send the key(FOO) to user's browser.
browser: get the key(=channel name=FOO) and open the web socket channel(FOO). and also displays QR code(FOO).
user(smart phone): user launch smart phone app(already logged in). and scan the QR code(FOO). user smart phone app send a login acceptance request to the server with QR code's information(FOO)
Backend: server send securely generated login key(BAR) via web socket channel(FOO).
browser: get login key(BAR) via web socket channel(name is FOO) and redirect to login url with login key(BAR).
server: get the login key(BAR) and let the browser to log in as the user
login request key(FOO) could be a JWT(contains key, url, expire, etc..) or just secure string(varies depending on the scenario). it doesn't contains account information and server must store it.
login key(BAR) is usually a JWT. with JWT, it contains account information and server does not have to store the key.(stateless)
I think you wanna do something like WhatsApp’s web where the users log to the web app by QR code, if I was doing such implementation I’ll do it as follows.
When the user arrives to the login page, we create a logInSession with a random token and we save it to the database.
we send that random token to the browser, which will render QR code based on the random token. We start a pooling for ‘log_me_in’ view to check if the user scanned the barcode.
The user goes to the mobile app and select log-on browser activity which will launch the camera.
Once QR is read on the phone, make a request to the backend with the scanned token and update the logInSession with the username.
With the next call to ‘log_me_in’ view, log the user in based on the username and tell js to redirect to homepage.
Hope this is clear enough.
I have set up Django OAuth Toolkit in my project where the authorization server is separate from the application server (i.e accounts.example.com and app.example.com). App server redirects to accounts server using authorize flow; the user inputs credentials to sign in to auth server, then auth server redirects the user back to application; so that the app can retrieve tokens.
The above flow currently works as expected. If I do not click explicitly Log out the user and the application signs out (e.g session expires or browser cookies are cleared), the above flow will be performed again and there won't be a need for credentials because auth server still knows who is signed it.
However, I am having trouble with explicitly logging the user out of the application. If a user explicitly clicks login, firstly, the token must be revoked and secondly, the auth server must sign out. What is the proper way to achieve this? As far as I am concerned, I won't be able to use Ajax to log out the user because the session must be destroyed in auth server.
So, I have been thinking of redirecting the user to accounts.example.com/signout?token=${accessToken}&client_id=${clientID}. However, I am not sure if this is the right approach. Is this how these sign out requests work with OAuth? Does that mean that when I sign out from the system, I need to always provide Access Token and Client ID?
I'm trying to use Federation from a User Pool. Note, I am not talking about Federated Identity Pool a different concept.
Is there a SignIn API for federated users or is just a hosted UI
Does the app "have to" open a browser on a Sign In URL that looks like https://XXXXXX.au=th.XXXXX.amazoncognito.com/login?response_type=code&client_id=XXXXXXXXX&redirect_uri=XXXXXXX? Can the end-user can stay inside the app, similar to how Google SignIn API on Android works (it pops up a small Google sign in UI, user clicks on their name, you're immediately back inside the app with a token.
How do I launch a browser on that Sign In URL?
How can my app be called back when the user has finished signing in?
Specifically how does my mobile app receive the token from the browser?
Is there a SignIn API for federated users or is just a hosted UI?
As far as I can tell you have to use the hosted UI when you federate a user pool to social IdPs.
How do I launch a browser on that Sign In URL?
This depends on the language and platform obviously, on Android with Xamarin you can use Xamarin.Auth.Presenters.OAuthLoginPresenter.Login() to launch a native browser Chrome at a URL specified by the OAuth2Authenticator you pass in. That OAuth2Authenticator does more than just craft the URL it gives Chrome, its stateful so when you get an answer back in the form of a code or token, you can then call methods on that object to proceed.
How can my app be called back when the user has finished signing in?
Specifically how can the browser redirecting a URL actually redirect you back inside the app. That's done via something called, Deep Links & App Links, here's that concept explained on Android.
I want to integrate DocuSign with my application. There is no recipient.
The user who is signing in my application should sign the document which is generated through my application. After signing the documents through DocuSign, the user should be returned back to my application.
I don't want any email authentication.
How can I do that?
Yes, no problem! Use the embedded signing option. See the recipe.
This enables your app to provide the following flow:
The user logs in to your app
Your app logs into DocuSign using an admin login for your DocuSign account. The login is done from your app to DocuSign. Your app's user does not login to DocuSign.
Create the pdf (or other file type)
Your app sends it to DocuSign using embedded signing. Your app receives back a specific url to enable the user to sign.
Re-direct user's browser to DocuSign by using the specific url.
User signs
User's browser is re-directed back to your app
Your app can download the signed document if you wish
Also: Mobile devices are fully supported, including signing via the touch screen. Do not use an iFrame if your users will use mobile devices.
I want to be able to authenticate users of an angular.js application using oauth, but I do not want to store any tokens on the frontend because I have seen that it can be fairly complicated to do so securely. Is there a way to pass some sort of credentials of a user to my django web application, where is can authenticate the user with some oauth provider and save that information in a session? To make it simple, here is the process I want
User is logged into some oauth provider, i.e. stackexchange
They click a "login with stackexchange" button on the front end angular app
Their login credentials are sent over to the django application through a restful api
The django app which receives these credentials attempts to get a token using rauth
If the server receives a token, the user is logged in and their information is saved in a session, otherwise they are given an error
Is this sort of process supported by OAuth2 providers?
Step 3 is incorrect: that authentication process is handled entirely off-site, on the OAuth provider's infrastructure, e.g. StackExchange.
This kind of flow is certainly possible. I would check out the Facebook example, which uses Flask, but provides a similar framework for how you might go about this in Django.