I'm using the identity API in my Chrome extension to authenticate users and prove to my backend who they are. This works fine for the most part, I use getAuthToken to get an OAuth access token that I send over to the server, which it uses to confirm the user's identity.
The only problem is this: the first time getAuthToken is called, the user is asked to choose a Google account from the list of accounts they're currently logged into. Any calls to getAuthToken after that though just keep reusing that same Google account without prompting the user. I'd like to give users the ability to choose a different Google account later. Seems like clearAllCachedAuthTokens would be exactly what I need - and it works - but only when the chosen Google account isn't the account that's logged into Chrome. In that situation, clearAllCachedAuthTokens doesn't do anything.
The only way I've found to reset the locked in Google account of getAuthToken that works even when the user chose the Google account that's logged into Chrome is to get the user to log out of Chrome, which is annoying and awkward. Is there a better way?
Related
I'm working on a react app where the pages can be used both by authenticated and anonymous users. The pages show more features for the authenticated users.
If a user previously has signed in and revists the website, I want the user to be automatically authenticated, and am struggling to achieve this.
I'm using redirect methods because I don't believe popup is working well on phones (is that assumption correct?).
I have tried storing the homeAccountId in local storage and use that to get the account used and then calling login in the msal instance. I also set up a addEventCallback and listen for EventType.LOGIN_SUCCESS which I use to set some internal state about the logged in user.
I have tried using MsalAuthenticationTemplate but strangely this doesn't invoke a login. I have also tried to detect if this is a "first run" and then invoking the login, but that doesn't work all the time. Sometime I get a SSO error indicating I should provide a login_hint or sid which is not possible because I use B2C.
If I don't do anything the user can click the login button and if the user has a valid cookie with B2C the user is logged in without providing credentials which is a strange behavior for the user because my website indicate the user is not authenticated (and show no logout button).
So I can't really get this to work and are wondering if somebody has a concept for achieving this?
Please checkout the msal-react samples which all demonstrate the behavior you're looking for. The MsalAuthenticationTemplate would be the recommended way to do this and if you're still having issues getting this to work after reviewing the samples I would recommend opening an issue on our repo with code snippets so we can take a closer look at what's going on.
Also using localStorage, if you're not already, would help to maintain application state between browser sessions. sessionStorage is the default.
As for B2C not asking for credentials; server state is separate from client state. You can be signed in on the server without the application knowing about it. Until your application makes a request to the B2C server your application will show that a user is not signed in. If a session already exists on the server when you make a login request, the server may redirect you back to your application without asking for credentials again.
Basic scenario: Azure AD is used as just an authentication provider a web app, the identity retrieved from azure is matched by email to a local identity and a forms auth cookie is issued for api authorization against the app's webapi.
Problem: If a user has multiple azure accounts, they may be pre-authenticated when they come to my app. In this case, when the redirect back to my app occurs there may be no matching user and login cannot complete.
Desired Solution: If the cached azure account is invalid for my app, I would like to direct the user back to the microsoft login page with a chance to manually type in their credentials
How do I achieve this, and is there something wrong with this flow? It seems currently the only way for the user to get into my app is to go to azure and log out of the bad account. What other methods could achieve a better user experience? Should I use the auth token from azure and log the user out programatically and then back to azure for another go around? Can I hint for azure to prompt the user even if they are logged in already?
I discovered that I really wanted the prompt=select_account flag on the redirect to azure, but the library I was using made it difficult to determine how to set this. I am using the ms-adal-angular6 library, which is a wrapper for azure-activedirectory-library-for-js.
After digging through the code I found a config property that was not documented called extraQueryParameter which when I set to "prompt=select_account" got the behavior close enough to what is needed.
Ultimately the user must select their account every time, instead of just when the account is wrong. I could most likely get tricky with the error response and redirect back a second time with prompt=select_account to get the behavior I was looking for, although the library doesn't make it easy to change this on the fly either so I may stick with it always on.
I've integrated Azure AD B2C into my web app and I'm using MSAL on the client. I'm using Google for a social IDP.
Using Chrome, I start out with only one Google identity (foo1#gmail.com). My app calls loginRedirect(...) and I'm able to use foo1#gmail.com to successfully login with Google. If I then close that browser tab (but not the browser), open a new one and have my app call MSAL's loginRedirect() again, I am automatically logged in as foo1#gmail.com and everything is good. Presumably a b2clogin.com cookie is being used to remember the previous login info.
If I then add another Google identity to the mix (foo2#gmail.com) the behavior changes. Repeating the scenario above, when my app first calls loginRedirect() and I try to login via Google, I'm asked to choose between foo1#gmail.com and foo2#gmail.com as expected. I choose foo1#gmail.com and I am logged in just fine. If I then close that tab, open a new one and have my app call loginRedirect() again, I am automatically taken to Google's "Sign in with Google / Choose an account" page where I have to pick between foo1#gmail.com and foo2#gmail.com. It appears that enough information was stored by AADB2C to know that I was previously logged in via Google, but the actual Google identity that was used previously is not automatically selected as I expected.
Following the guidance in this article I can work around this by a) storing the last used email address in a session cookie and then b) passing the email address in to Google as a login_hint, but it seems that this will only work with Google. We would prefer a solution that will work for any social IDP.
Is there a way to get AADB2C/Google to automatically select the previous identity without using login_hint?
What you are experiencing is the login behavior of Google rather than Azure AD B2C.
Google remembers who is signed in to the current session (e.g. foo1#gmail.com) as well as who has signed in to the current browser in recent sessions (e.g. foo1#gmail.com and foo2#gmail.com).
(Google also allows multiple sign-in.)
The use of login_hint by Google is documented at here.
login_hint is an OpenID Connect concept -- which is why Google, as an OpenID Connect provider, supports it but many OAuth 2.0 providers don't do so (at least support it in a standardized way).
How would I authenticate with Firebase in a chrome extension? I need to specify the allowed domain list in the Forge. Chrome domain for the extension is just a big hash-like string.
I did read this: authClient.login problems
But the hashed based domain of a chrome extension is not being accepted in the Firebase forge. Is there another way to go about it? Currently am just reading the cookie firebaseSessionKey to just assume that I am logged in. But surely that can't be as secure as letting Firebase validate this session key.
As Rob points out, authentication cannot work in an environment that does not enforce origin restrictions. The fundamental problem here is that any authentication provider (Facebook, Twitter, Persona, or your own service) cannot issue an identity to a browser - i.e. it is meaningless to use Facebook to login to your browser (or extension).
The F1 add-on for Firefox ran into a similar problem (http://f1.mozillamessaging.com/) - where you would authorize F1 to post on twitter/facebook on your behalf. The extension had a website to along with it, from where you would serve the login page and proceed as you would normally in a web page. You'll need some code to communicate between the web page and your extension, chrome provides the tools necessary.
I would recommend the same approach - create a web page on a real domain (Github pages is awesome for this) to go along with your extension. This means your extension can't work offline, but neither can your login or writing to Firebase!
This will work using Google Plus Login Flow which I believe is the only one that allows cross authentication so the scopes are Google Plus Login.
"www[dot]googleapis[dot]com/auth/plus.login"
So what is happening here is you will get the access_token from the extension which you will be sending to firebase with the request using authwihtoauthtoken specifying google as a provider along with the access_token acquired from chrome.identity.getAuthToken()!
https://www.firebase.com/docs/web/api/firebase/authwithoauthtoken.html
Now the fact is that this access token could be issued by any other app, so we need to make sure that it is valid and has been issued for our app, basically we need to know there isn't man in the middle trying to access our database.
This verification is being made by the firebase.
They will check if this token belongs to the same application as the token has been issued to.
So you will need to create another set of credentials under the same application in the google developers console as for your extension. We will be basically doing the same thing as if we were to do it for our webpage but we will be inserting this new set of credentials to firebase's google oAuth in their security section.
They will do this check for us there. They will verify with google if the token is issued to the same app.
That's it.
Background Information.
https://developers.google.com/identity/protocols/OAuth2UserAgent#validatetoken
Use case
Sending ID tokens with requests that need to be authenticated. For example, if you need to pass data to your server and you want to ensure that particular data came from a specific user.
When to verify the access
All tokens need to be verified on your server unless you know that they came directly from Google. Any token that you receive from your client apps must be verified.
Google has a tutorial how to do this for python found at:
"github[dot]com/googleplus/gplus-verifytoken-python"
So basically what is happening here is; instead you doing to verification from on your server, firebase does this verification for you when you enter the CLIENT_ID and APP_SECRET into the firebase and enable the Google Authentication.
The way to do this correctly is a combination or same style of verifying to whom the client_secret was issued. Chrome will give you a access_token and then this access_token will be checked on the firebase's backend.
I've integrated CocoaLibSpotify with my iOS app, and I wonder if there's a way to save the user from having to enter credentials if they've already signed in to the Spotify app on their phone.
I know Spotify doesn't support OAuth, but I did want to ask if anybody knows if Spotify (1) plans to support OAuth in the future, or (2) is working on another way to spare the user from re-entering credentials into another app for the same service.
This isn't possible with CocoaLibSpotify — the first time the user wants to log in, they have to enter their credentials.
Once that's done, CocoaLibSpotify has APIs for saving the user's credentials and using them next time, though, so the user only should ever have to input their credentials once. To be honest, since an app with OAuth would have authenticate the user once as well, the method CocoaLibSpotify uses isn't really extra effort for user.
Look at the delegate method session:didGenerateLoginCredentials:forUserName: to get the credentials after logging in, and the attemptLoginWithUserName:existingCredential: to log in again next time.