Firebase Auth - Activating SSO login methods for existing users only - firebase-authentication

I'd like to implement SSO logins for users in my Firebase web app, but only for users that have an existing account. When I add e.g. the Microsoft provider in Firebase and implement the required UX flows in the web app, anyone with a Microsoft account is able to sign in using that, upon which a new user account is created (if they haven't signed in before). I'd like to restrict this to users that:
have registered previously with e.g. an email and password login method, and
have subsequently chosen to activate the SSO login method in the web app
Is there a recommended way to prevent the default behaviour in Firebase auth for SSO so that I can check for an existing account with the same email and its approved login methods before letting the user log in and/or create a new account?

There is no built-in way to do this in Firebase Authentication, as it makes no distinction between sign-up and sign-in for OAuth users.
The typical approach to implement this is to create a list of the allowed users somewhere that both your app and your server-side logic can find it (like in one of Firebase's databases), and then check against this so-called allowlist in both your client-side and server-side application code (and security rules) after the user signs in and before executing any other application logic for them.
In the application itself, you could show this as "unable to sign in" to the user, since (despite you calling the Firebase API and signing them in there) they have not completed the sign-in into your application itself.

Related

Is it possible to authenticate a user using google identity without provider's sign in page

Background
I have a web application "APP1" (front-end: Vue.js & Back end:Azure function) deployed in azure app service. I have implemented client directed sign in (easy auth using this), after that I can authenticate user using provider's sign in page [both AAD & google].
Target
I have another web application "APP2" deployed in on-primes server. I want to redirect to APP1 from "APP2" and automatically sign in without provider's sign in page. I will read credentials from environment variable.
Tried solutions
I have found a similar issue here, however I am unable to use the solution because the DB between AAP1 and AAP2 can't be shared
I have also checked the google identity providers documentation, however I am unable to find how to programmatically sign in without provider's sign in page
Question
Is it possible to programmatically sign in to google identity to get token without provider's sign in page
The whole point of google identity is to prove the identity of the person behind the machine.
OpenID Connect is an open standard that companies use to authenticate (signin) users. IdPs use this so that users can sign in to the IdP, and then access other websites and apps without having to log in or share their sign-in information. (id_token)
OAuth 2.0. This standard provides secure delegated access. This means an application created by a developer, can take actions or access resources from a server on behalf of the user, without them having to share their credentials (login and password). It does this by allowing the identity provider (IdP) to issue tokens to third-party applications with the user’s approval. (access_token, refresh_token)

How to login into Google workspace using OIDC with my own identity provider

I am building an SSO system for android where I am the identity provider. And I want users to sign in from my app that will automatically log them in to google workspace (or any other enterprise application e.g salesforce). I cannot figure out what and how to send identity values from my Idp to Google workspace.
This can't be done this way round. When a user signs in to your app she can't be automatically signed in to any other application. The options that you have are:
When a user signs in to your application you can ask Google for an access token. As part of your sign-in process, you can run an OAuth flow against Google Authorization Servers and ask for proper permissions. This will allow the user to additionally log in to their Google account, consent to release information to your app and you will then get an access token that will enable you to call Google's APIs. This way your users will have to log in twice (both to your app and to Google).
You can rely on Google to log users into your app. So, Google will be the OIDC Provider and your app will only be the client. People will log in to their Google account, and you will get an ID token in return. You can use the data from the ID token to create user accounts and sessions in your app.
In the first case, you will want to have a look at OAuth flows, like the code flow. In the latter, you will need OIDC flow, e.g. the OIDC code flow.

What is the correct way to use OAuth for mobile and website consuming my own API?

I have a question more related to the way OAuth 2 is working but since using IdentityServer to implement OAuth I think it's relevant. I could not find an answer anywhere.
I'm building a website and a mobile app that consumes my own API. Each user of my app will have a username and password, that will give him access to the app/website and though the API to his information.
I'm not sure about the right way to handle the flow for user login:
On the website I have my own designed login form. I don't want to move the user to my auth server to login, and then have him approve the information he gives - he is the user on my system - I have access to all information - kida like facebook has a login and access to the informatio - they don't ask what you're willing to give them. So is implicit really the way for this?
On the mobile app I also have a login form and now I read here (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-native-apps-10) that the OAuth approach is to have the login in a WebView?? Doesn't look like facebook login is in a WebView on their mobile app.
The approach I was first lookin at is the Resource Owner. Users will login, get the token and the refresh token and can start working against my APIs. But storing my client_id and secret on the mobile app? on the website javascript files? doesn't feel right. I can of course make a call to an API that will mask those and be a proxy to the login process... but... (read #4).
In the future I would like to allow access for third-party developers. For them to allow login for users of my system I will use the implicit flow. Also, I plan for those developer accounts to have restricted API access (for example, the number of calls to the API will be limited by plan). What prevents those developers from asking for the username and password of their account on my system on their website, getting the response from my servers with the access token and refresh token, and using my API however they want, without restrictions, and having access to the entire user profile?
Lets say I'm sticking to the resource owner flow, receiving back from the server a token and a refresh token. What should I store on the mobile device and how? What should be stored in the browser and how? the refresh token? and each time he opens the app get a new updated token with that refresh token?
Edit
Just to clarify, because I find a lot of lectures and articles that explain the process from an API consumer point of view (ie. the third-party developer): I am the API owner and the auth server owner, I'm the owner of the user accounts (they are my users of my services), I'm also my own consumer (though the website and the mobile app), and in the future I want to enable third-party developers to allow my users to login with their accounts of my service (kinda like Facebook or Google)
You're correct that you shouldn't store the client_secret in your app, but I doubt you will get around storing the client_id. You could disable the consent screen for your app as well, and build a native login view. You need to store the access_token and the refresh_token on the device (maybe encrypted in a database) if you don't want the user to login everytime they use your app.
As for problem 4, you could do the following:
Embed the client_secret in your (web) app
Set up which hosts have access to your api on the IdentityServer
The IdentityServer generates a salt and sends it to the client
The client calculates a session_secret using hash(ip_address + session_salt)
The client uses the session_secret and the client_secret for the API call
Server validates the hash and client_secret
It's nearly impossible to completely prevent someone from using your API. But you should add various rate limiting methods, such as limiting IP addresses, API calls etc. But nothing will stop someone decompiling your app and accessing your client_id.

Multiple authentication levels in a RESTful API

Scenario
We are building a new RESTful API for our web application. This API will serve our mobile applications, our web application and authorised customers.
We are using Apigility to build the API and are making use of the OAuth2 implementation it provides.
Currently, our web application relies on a users table, with permissions assigned to each user. These users simply log-in using a web form, and the session is then stored and appropriate permissions checked upon access.
We want to be able to authenticate API access (such as our web app, and authorised customers), so no unauthorised access to the API can happen. However, we also want to authorize the permissions at a user level, therefore some sort of user authentication must also happen as well.
Any authorised access to the API may use a different user, so relying on a single user per client will not work, especially since the permissions are on a per user basis. We also do not want any user to be able to use the API without prior authentication, so wanted to avoid adding every user as a client to OAuth2.
For example:
The web app is authenticated with the API with two users using it:
UserA has user management permissions
UserB does not have user management permissions
Therefore, UserA can POST to /users and receive a 200 OK while UserB should receive a 403 Forbidden.
What we have tried
We have created an example application, and have successfully set up authentication using OAuth2 for the high-level clients and can make calls as expected. But we have not been able to create an authorization model for our users based on this.
We though adding a custom HTTP header with a user token that is provided after an authenticated call to /user/login. But we are not sure if this is the correct method.
The question
How can we both authenticate the high-level clients (such as our web app, or authorised customers) but then authorize access based on the user actually using the system?
You have a few options available to you:
Token-level permissions
You can provide different tokens for each user account, and tie permissions to the token. This runs the risk of the wrong tokens being mixed up with the wrong users. However, this also has the advantage of not having to maintain a user<->token relationship, as the permission is decided at the token level. How you decide which token to generate can be tricky.
User-level permissions
You can tie a user account to a token and that user can then be given read/write permissions. This reduces the risk of a user having a wrong token as they're linked. With this method, you can use the same method of token generation for all user accounts as the token is ignorant of the permission, but does allow them "access" to the API (thus preventing unauthorised access).
I've deliberately avoided mentioning specific types of authentication tokens, as these two concepts can apply to most of the popular choices on the web (token-based, OAuth based).
OAuth has no concept of Identity.
You should look into using OpenID Connect which is a profile on top of Oauth 2.0.

Webhook + Server-side Authentication

I have a user provide me the organization he wants to Sync with our system. We create the hooks afterwards for each App of the Organization.
The only workaround I found is to ask for each App ID and Token or the username authentication.
How can a Webhook be authentified to have the right to get items from all Apps at the same time? (like a server-side authentication)
There are a couple of options: The best is to contact Podio support and get an increased trust level for your API key. Then app tokens can be retrieved through the API and you can fully automate hook creation.
The alternative is to create a user that's a member of all spaces which you can authenticate as using password-based authentication.