Limit Microsoft OAuth authentication to only authenticate webapplication, not all microsoft services - javascript

I am using firebase for a website, where users can sign in with their microsoft accounts via OAuth 2.0:
import {getAuth, signInWithRedirect, OAuthProvider} from "firebase/auth";
(...)
const provider = new OAuthProvider('microsoft.com');
const auth = getAuth();
signInWithRedirect(auth, provider);
It prompts the Microsoft Single Sign-on with a redirection work-flow.
The authentification works nice with firebase, except one detail:
When I sign in with the Microsoft account in the browser for the webapplication, I am also signed in to my complete Office 365 account in the background and other potential microsoft sites.
So if I open a new tab and go to the my Outlook 365 online mail, then I am already logged in since I logged into my webapplication. If I happen to forget to log out from the webapplication, my entire mailbox, calendar with all the microsoft account information are exposed.
I have looked through all the pages and settings in the Azure Portal where I set up application/tenant id's, looked at Scopes and looked at OAuth 2.0 parameters from the Mirosoft documentation,but I can't find anything about this issue.
Single sign-on is originally made as a convenience for the user, but in my case I would like to prevent it as a security measure.
How can I limit the microsoft sign-in to only authenticate in the webapp/firebase project, and nothing else?

The simple answer is - you can't do that.
SSO is exactly what it means - Single Sign-On. The user logs in once and can use different apps without the need of authenticating again. You ask Microsoft to verify the identity of the user for you. Microsoft logs the user in and gives you back the answer. But it means, that on this browser the user will be able to use other Microsoft services as they already verified their identity.
The only thing you can do is to inform your users about the security risks and tell them to make sure to log out at the end of their work (you can then log them out at Microsoft as well).
If MS supports backchannel initiated log out, then you can try to implement some action that will check if your user's session is still active, and if not, then initiate a logout at MS. I don't know if they support it though.

Related

FIDO2 / WebAuthn Heuristic discovery of ambient /pre-authorized user(s) at authentication time

Edit respose to #cody salas
Following on from your sensible and detailed break down: -
Require Username:
Yes this seems well understood. The RP prompts for username/other-id and finds all credentials that are offered up in an array to the authenticator. Peachy!
Usernameless:
I need the "nuance" you refer to please. What (if any) filter(s) is applied to the returned credentials?
Global scope === Windows Hello User
Google login(s)
Other App logins
My Windows Hello Identity does NOT work with my Yubikey so I can't test :-(
Shared Accounts:
Ok, forget about the Beatles analogy, let's imagine one user (Our ex-PM :-) with multiple identities. ScoMo-Treasury, ScoMo-Health, ScoMo-Resources etc. What does a wildcard GET return?
End Edit 1
UA Credential Safe interogation.
Scenario:
Tri-Bank has 1 or more registered users from this device (My Windows Hello PC "Bad Boy").
There is no active session or ambient user to the RP (sub)domain. (Seeing local/session storage deprecated but all cookies also expired)
I simply cannot see a usernameless login interaction possibility
I will investigate that UPVA is deterministic on multi-user device but the spec is not only non-canonical, it seems to be off in fairy land :-(
WRT: -
Authentication WebAuthn-3 and Authentication WebAuthn-2
Please expand on point .2
The script asks the client for an Authentication Assertion, providing as much information as possible to narrow the choice of acceptable credentials for the user. This can be obtained from the data that was stored locally after registration, or by other means such as prompting the user for a username.
Which spec can we refer to (CTAP-10?) that will enlighten us to what is returned to a GET call with an empty "allowCredentials"?
How can the RP refine the user selection granularirty without a .GET that either identifies a single user or returns new Error("non-deterministic");
Does no one else see this as pivitol?
If we always have to ask for username please just say "We always have to identify username first!"
Otherwise could the user be prompted for we have Ringo, and Paul registered; which one do you want :-(
And yes, I know Paul can't login to Ringo's account without his thumb. I'm alluding to the unacceptable disclosure of Ringo's financial activity to Paul. Probably not a big deal unless it was John :-)
Please explain the FIDO2 versus OAUTH2.0 philisophical diversions pros/cons here!
OAUTH2.0 :- Would you like to continue as dicky#gmail.com? Done! no password, biometric, PIN, blah, blah, blah, pre-authenticated and trusted
FIDO2 :- I've got a UPVA that I'll probably have to test you on or a number Authentication methods for a number of users that I'll get you to pick from
Sounds about right???
Let's break this problem down into three different sections: Requiring a username, usernameless logins, and shared accounts
Requiring a username
Using an identifier is the only way to narrow down which authenticators are acceptable for an auth session. Note the use of identifier. The spec calls out username as it's extremely common, and familiar to users, but another mechanism can be used as an identifier if your environment/requirements allows for it.
Also keep in mind that this flow works well for users who are using an authenticator or ecosystem that does NOT support discoverable credentials.
I have some development guidance here if you wish to see some expanded code samples.
This won't entirely solve your problem if you are using a shared Windows Hello account. All John has to do is type the identifier "Paul", type in the PIN/Fingerprint, and have access. Overall you don't want to share authenticators, but I'll touch on that later in this comment.
Usernameless login
Remember this login flow will only work for users in an ecosystem that supports discoverable credentials. You've mentioned Windows Hello so you are in good hands. In this flow a relying party sends an empty allowCredentials list because it has no idea who is triggering the auth session. The relying party is essentially saying "send over a credential, and I'll attempt to validate it". There's more nuance to this statement, especially depending on the identity provider you are using, but that's the overall gist.
Usernameless can be broken down further depending on if you're using a security key, or platform authenticator. But during the GET() ceremony all credentials tied to your current origin will be shown depending on the authenticator that you activate. So if you fingerprint into Windows Hello, all the credentials for the current origin tied into the single Windows Hello account will be shown. If you activate your security key, all the credentials on the device for the current origin will be shown that exist on the device.
Shared accounts/workstations
So we'll continue with your Beatles example above. They can all share one computer, but this is where you need to question if they should be sharing the same Windows Hello account. If you register a credential using the Windows Hello authenticator, then anyone with the PIN/Fingerprint to that account will be able to leverage credentials on the account + device combo.
At the end of the day this will depend on how many accounts are tied to your workstation.
If you are adamant about the Beatles all sharing one Windows Hello account, on one workstation, then maybe they need separate personal authenticators, like a security key. That way no matter who is using the shared account, they still have independent credentials (unless Ringo decides to register Windows Hello, rather than his security key)
Otherwise, if each Beatle has their own Windows Hello account, they could log out/login in whenever one of the lads needs to check their bank account. In this case they will only be shown the credentials tied to their specific Windows Hello account
Hope this helps
Update 8/22
Glad my responses are helping so far - see below for answers to your additional follow-ups
Usernameless nuance
When I say nuance, I’m mostly referring to the not “one size fits all” of identity/auth providers. I can give you the code to my project using Cognito, but if you’re using Azure AD then there might be differences in the parameters that you pass to your RP. MOST of the code and logic will look the same, but it’s the small differences that might require more/less data.
For instance, let’s say that both Identity providers A and B support WebAuthn, and both will support discoverable credentials/usernamless login. But imagine that A requires that you call to its API noting the user's identifier, and B can derive the identifier from the get() response. They both accomplish the same task, but require slight modifications to the implementation
Shared accounts
I ran a test on my Windows machine (Windows 10, Windows Hello consumer). I created a Discoverable credential on account A using Windows Hello. I signed out, and logged in as account B using Windows Hello. I attempted to login to the same website, but I was unable to use the credential created by account A as account B.
So if your PM creates a credential as ScoMo-Trasury, they won’t be able to use the same credential as ScoMo-Health.
The wildcard get() method will only return the credentials for the account currently logged into Windows.

Gmail JS API - OAuth2 Error invalid_scope

I am new to GMail JS API and I was trying to read gmail emails using Javascript according to the quickstart tutorial given explained on below link
https://developers.google.com/gmail/api/quickstart/js
I have followed all the instructions given on the page but I am getting below
error
did I miss something???
Please help me resolve this error
Thanks in advance!!!
You may refer with this thread. Make sure that you are authenticated to the API properly.
To do this, there are two ways:
use OAuth - the Server redirects the user to google's servers, where they can login, grant permission to your app, and pass a token back to
you
Service Accounts. These are a little bit more complicated:
First, you'll have to setup an app (done)
second, you'll have to setup a service account. This is how your app authenticates to google. you've done that, and the certificate
you've got contains the private key to authenticate
third, the user needs to grant your application access to act on behalf of them. This is the point you haven't done yet.
Also, as stated here, certain scopes simply aren't supported for the oauth2 for devices flow.
Additional references:
Invalid scope error when trying to access gmail api
You may refer with this thread.
As per the announcement on May 11, 2017, publicly available applications with access to certain user data must pass review. If you see an access error for your app, submit a request using our OAuth Developer Verification form.
For personal-use apps and those you are testing, join the Google group Risky Access Permissions By Unreviewed Apps, which allows you to approve data access for personal and testing accounts. See the Google API Services User Data Policy for more information.
This blog about how to fix this error might be also helpful.
OAuth invalid scope

Are Javascript Instagram applications that authenticate with client_id allowed?

A few web-based applications I maintain have been using JavaScript on the page to fetch posts from Instagram* through their API, only authenticating with a client_id. With the Instagram API changes recently (applications are sandboxed until approved) this no longer works.
Is this kind of application allowed by Instagram? Or is it considered a security risk to expose the client_id in the Javascript that performs the request? If it matters, the application is for internal use by a few employees only.
* Specifically, the 10 last posts from a fixed user.
All instagram API endpoints now require a valid access_token rather than client_id. The search endpoint is an example of one that didn't previously require an access_token. You can find this in the Change logs
All API endpoints require a valid access_token
All API endpoints require a specific permission scope granted by the user
You can authorise your own account and grab the last 20 posts, but for any more than that you will need to submit your app for review
Try to create a new app.. My app was deleted instead of going to sandbox mode.
As you need 10 last posts, this should work on sandbox mode.
Content Display for Personal Website. If you are a developer and you want to showcase Instagram content on a website, then you do not need to submit your app for review. By using a client in sandbox mode, you will still be able to access the last 20 media of any sandbox user that grants you permission.

Firebase in Cordova/Phonegap: Log in using Email/Password from within app?

I'm running a webview from a cordova app and want to authenticate a user, I know they have the OAuth strategies but I need to use the email/password combination.
I'd like to keep things simple but may end up having to generate a token.
Open an InAppBrowser that loads an auth flow for firebase
Listen for that auth flow to be completed using this method: http://blogs.telerik.com/appbuilder/posts/13-12-23/cross-window-communication-with-cordova%27s-inappbrowser
Grab the result from the webview again and insert it into the webview firebase instance
I'm guessing that's not possible due to security.
My app is using Amazon login (required) so my alternative would be:
webview loads InAppBrowser with our external url
that loads Amazon auth, then generates a token for Firebase
webview listens for token and grabs it, stores it in localstorage
Edit:
In the firebase docs on logging in with a username/password, I see it returns a token for the session and more information in the authData object:
https://www.firebase.com/docs/web/guide/user-auth.html
Could I then take all the information from that object and send it back over to the cordova webview and then populate that Firebase ref with the information?
Some answers from the wonderfully helpful support at Firebase:
First:
You’re correct – anyone can make a request to sign up, and we don’t expose any capability to secure the url which people can sign up from for email / password authentication.
The main reason that we require / enable origin whitelisting for OAuth authentication, but not for email / password authentication, tends to revolve around sessioning.
The Firebase login server does not maintain sessions (via cookies or any other method), and so requests to the login server for password auth. requires a user credential (the password) for every request. CSRF is typically a risk when a malicious party can take advantage of a user’s session browser, i.e. make requests on behalf of the user to some page where cookies are automatically sent by the browser.
Furthermore, we don’t have a great way to actually do ideal origin-based whitelisting for these pure HTTP requests. We could use CORS, but would have to fall back to JSONP for older browser environments that don’t support it. To complicate matters further, PhoneGap / Cordova apps don’t have the same notion of an “origin” at all, and from the perspective of a server – the calls are indistinguishable from any malicious party making an HTTP request with the same headers.
The OAuth providers, however, use cookies for sessioning and do not require user invention for each auth. request. If you’ve approved a particular Facebook app, you won’t be shown any UI/UX or be prompted the next time that app requests your data – it will be invisible. When we do OAuth, we never have to send any user credentials to Facebook / Twitter / etc., because those are stored in browser cookies for facebook.com / twitter.com / etc. What we need to protect is a malicious party pretending to be a popular, valid Facebook app. and taking advantage of that short-circuit behavior that would get access to user data without the user’s knowledge.
My response:
So, how is that secured? If anyone can make a request to sign up from a
cordova webview (which comes from no specific url, just the app iteself)
then I can't secure from which url people can sign up from? So any site
could use our url "xxx.com" in their config and start registering
users?
That doesn't seem right to me.
I think I still need to have an external url that is whitelisted by you
guys. That would have the login form and do the auth.
But then my question is, can I transfer that auth back to my cordova app?
Is it somewhere in localStorage I can check? I'll have to run some tests.
And final response:
Sure thing – we’re happy to help. I wrote much of the original client authentication code, and can speak to the design decisions and rationale that went into it. Be sure to let me know if you have further questions there.
While we don’t store user passwords in cookies, of course, we maintain a Firebase auth. token in LocalStorage. Our authentication tokens are signed by your unique Firebase secret (so they cannot be spoofed), and can contain any arbitrary user data that would be useful in your security rules.
By default, and when using the delegated login (email + password) service, these tokens will only contain a user id to uniquely identify your users for use in your security rules. For example, you could restrict all writes or reads to a given path (e.g. write to /users/$uid/name) by the user id present in the token (“.write” = “$uid = auth.uid”). Much more information on that topic available on our website.
Your plan to spin up a server to authenticate users with Amazon and generate tokens sounds correct. This is a common pattern for our users who wish to use authentication methods that we don’t support out-of-the-box (ie Amazon OAuth) or have custom auth requirements. Note: once you’ve created those tokens and sent them down to the client, they’ll be automatically persisted for you once you call ref.authWithCustomToken(…). Subsequent restarts of the app will use the same token, as long as it has not yet expired.
This is a topic of interest to me too as I have implemented something similar , twitter digits (native android) + firebase custom login in webview.
I think, as recommended by firebase, you can use other authentication providers and then the firebase custom login.
Do you use the Amazon login in android native code ? If so after login, then generate a JWT token for firebase and use it to access firebase.
If all code is in Html/js app, then maybe you can use custom login and generate a token on your server after making sure its logged in to the Amazon.
The trouble with Android hybrid apps is the following: the JWT token (for firebase) should be created on secure system (eg. server side) not with android java code, other option for hybrid app is to do a http request to generate the token, but I find that less secure, anyone would be able to get a token by finding the URL, than I resort to generate token within android app code, you can change security key/seed for token when doing new releases.
In summary, I don't think firebase studied the problem of mobile hybrid apps.

Gigya Logout Issue

I am implementing gigya to authorise users from facebook, twitter, linkedin and gmail. Everthing works great as I need very little information. I am using socialize logout to logout users, but It does not work as desired, It logs out of the hosted site but not the service provider.
Is there any option that I might have overlooked that logs out users from the service providers? I using facebook, twitter, linkedin and google.
I appreciate any help.
Thanks,
Nick
Nick,
You can do this for Facebook by configuring a domain alias (CNAME):
http://wiki.gigya.com/035_Socialize_Setup/020_Facebook_Settings
This only applies to Facebook. For other service providers (twitter, google, etc), users will remain logged in.
I suspect the functionality will evolve as this issue receives more attention. For now, perhaps your site logout process should remind users that they're still logged in to (xyz) provider.
The answer is correct, so my comments are in addition to his.
The behavior you see is correct. Gigya is essentially a proxy for user connectivity and, therefore, represents a session to the social network for the site through which the user connected. However, the session with the social network provider is distinct as well, so Gigya does not presume that it owns the user's absolute social connection. As a best practice, Gigya recommends that your site/application alert the user to sign out from each network to which they are connected.
Although facebook provides a mechanism for logging the user out from facebook (as described in the prior answer), other social network connections should be terminated by the user. This is especially important for public/shared computers. To provide additional integrity Gigya also provides a setting called 'sessionExpiration' for connect/login that determines the longevity of the session.

Categories

Resources