Firebase - can't trust OAuth returned details? - oauth

The short version of this question is: If you use Firebase's OAuth capabilities to obtain a user's email address, do you still need to confirm/authenticate the user's email address yourself?
One of the usual benefits of using OAuth is that - depending on OAuth provider - you can get a confirmed email address, but is this really the case when using Firebase for a webapp, e.g. with a binding like AngularJS?
After a user authenticates, there seems to be two data objects - authData available to the client side, and auth available for security rules on the server side. While authData contains details such as name and email, but auth contains just a Firebase uid plus provider. Therefore, if I am to obtain that user's email address, it must be provided by the client, and hence can't (in theory) be trusted?
Based on my understanding of Firebase's documentation, if I were to use GitHub OAuth for my app, I'd need to do something like the following:
Get user's to log in/create account with Firebase/GitHub
Client JS retrieves the email address from GitHub OAuth response
Client JS "submits" this email for confirmation - could be done multiple ways
Email address should be saved in Firebase with status "unconfirmed" (such a field being read-only to the user)
I need my own server-side logic to process such email submissions and send a confirm email request, e.g. through something like Mandrill
I need additional server-side logic to receive the clicked confirmation and mark the email address as "confirmed" in Firebase
Therefore Firebase can help me with steps 1-3, but steps 4-6 need to be done via my own server-side code?
The answer to this question is therefore a Yes/No, but with some justification/explanation!

Thanks to #Kato for confirming my assumptions in the question were correct, so I'll explicitly provide this as an answer, as well as provide an alternative I hadn't thought of.
So the short answer is, "Yes, you need to obtain or verify the user's email yourself when using Firebase OAuth", and the steps I listed above is one way.
An alternate approach that still requires server-side code but doesn't require emailing, would be to have the user write their token to their users table entry and then have server side code use that to retrieve the verified email address from the provider themselves. e.g. with a GitHub authorization token and appropriate scope, you can retrieve the user's verified email and not then need them to verify it to you again.

Related

How do you implement the new DocuSign OAuth2.0 SOBO using eSignature SDK?

I'm in the process of converting an internal C# API that uses a legacy SOBO integration to one that uses OAuth 2.0 as required by DocuSign. The legacy application makes all requests to DocuSign using DocuSign credentials of an application user (a non-person) and injects SOBO data (email address) in the appropriate header when we need to generate an embedded sending URI and have it appear that the envelope was sent by a real person without using their credentials.
I have successfully converted another (non-SOBO) internal API using JWT grant, but I do not know how replicate the SOBO dependent workflow. Have read Matt King's article "From the Trenches: OAuth 2.0 and the new SOBO", but still a bit confused. I know how to extract userId from email address as mentioned in the article, but not sure what do with it. Similar to my legacy application, I am using a application user to get consent and ask for JWT token without prompting internal users for their consent. Is this still possible using OAuth 2.0?
Happy to help here. Once you've retrieved the user's apiUserName / userId you'll want to add it into the JWT assertion's sub line.
When you go to generate the token, if consent has not been provided by or for the user, our system will send back an error of "Consent_Required." See https://www.docusign.com/blog/developers/oauth-jwt-granting-consent for different methods of granting consent.
For individual consent, the user needs to go to a specific URL containing your clientId, redirectUri, and some additional scopes. If they hadn't previously consented to the scopes in your OAuth request they will be prompted to do this once. You can confirm consent has been applied by having them visit the same link afterwards, which will send them directly to your redirectUri.
Domain consent works a little differently -- you need to have an organization, a claimed domain, and the users you're providing consent on behalf of need to have an email address that is part of that claimed domain.
Happy to connect and walk you through it -- if you can open a ticket at support.docusign.com and in the details request they reach out to me I should be able to have the case transferred and work with you from there.
Regards,
Matt King

OpenID connect Userinfo endpoint for other user than current loggend in user

The following scenario:
You have sensitive and protected user infos (name, mail adress, telephone number, adress) securily saved in an authorization server (e.g. IdentityServer4).
You have an API loading data from a second database storing your own data (not the sensitive user data). This data is somehow linked to users (lets say we store documents and the document A belongs to the user with auth-id "XYZ").
The problem:
Now a single page application gets a list of documents and wants to display the name and email-address of the user that owns the document.
So far I understood the OpenID Connect UserInfo endpoint to ONLY return the user info for the current logged in user but not other users. So there is the need to get the infos for the other users somewhere else.
Solution 1: Copy the user info into the second database. That would leak sensitive data out of the secured autorization server, introduce the need to keep the data in sync (if changed on the auth server) which introduces a connection between the auth server to the second db or the auth server to an API endpoint.
Solution 2: Let the API access the auth DB and grab the data from there. Possible but introduces the DB connection to the authorization DB what is (in my personal opinion not good).
Solution 3: Introduce an endpoint (like the UserInfo endpoint) on the authorization server that lets the single page application request the user info by auth id. Seems most practicable but seems not to be specified?
Is there an official specified/recommended way to solve that? Maybe a specification to use the UserInfo endpoint for that which I have missed so far?
simply my.domain.com/userinfo/XYZ that returns the infos for the user with auth-id XYZ???
Following is extracted from the OpenID Connect specification's user info endpoint section,
The UserInfo Endpoint is an OAuth 2.0 Protected Resource that returns Claims about the authenticated End-User.
As highlighted section explains, it expose information about originally authenticated user. There is no way to obtain information about other users unless you have an OAuth 2.0 access token authenticated for them.
Also, embedding an endpoint to authorization server is not recommended. It brings maintenance burden as well as privacy issues. Also, this will prevent you from alter the authorization server (ex:- Your sell this app and that customer use Azure AD). So don't do such non-standard ways.
Proposed solution is to obtain the user name and email at the time user create this document. At the time of creating, I believe application have an access token authenticated to content creating user. So you can get claims from user-info endpoint and store them along with document. And when another user get the document, you can reveal user name and optionally email. May be you never reveal email but give the ability to mail the owner which would be handled at back-end.

What are you supposed to do with oauth2 confirmation redirects?

If I'm integrating authentication from a third party service into my app, such as github or slack for example, when a user goes to sign up on my app and successfully authenticates with the third party service, what does the data look like that I will receive?
Specifically, if this is a user's second or third time signing in, and they've already signed up before, how do I know they're already signed up? What data do I need to store in my database to know who they are?
Are there common maintenance or upkeep I need to perform on the data about a user's identity? Does it go stale?
The data you receive depends on the response_type and scope parameters of the request uri you are constructing when contacting the third party services. The id_token received is always a JSON Web Token (JWT).
When you request the "openid" scope, the id_token will have "iss", "sub" claims as part of the token payload. These two claims uniquely identify the user by who the provider is and the unique id for that user in that provider. The combination of these two values can be saved in your database to identify if the user is already signed up or not.
When you use a third party provider and save just the bare minimum information (iss, sub), then you do not have to keep up with any information. This would be a nice approach when you don't want to deal with any maintenance. If you need user profile related information you could request the "profile" scope as part of your request which will have more information about the user.
Thank you,
Soma.

Sending secure POST data to RESTful API without authentication

I am working with an Arduino that I want to send data to a remote or local Rails RESTful API of mine. When building its front-end, I can login with devise and authenticate. But I am wondering what happens when you want a third party device to POST data to the backend ?
One choice could be to use random generated long hashes as keys, as Twitter does (a client key for example and an API key) which of course is not secure but decreases the chances someone will POST data easily to another account.
However, If I am right, the data will be sent over an http connection so they could be easily sniffed. There is no problem sending temperature data, but If someone decides to send RFID IDs and names etc. it could be a vulnerability.
How could I send data with a POST request to a RESTful Rails backend API:
authenticated?
secured?
authenticaed?
You will need an endpoint that the 3rd party can call (let's call him Zed). Zed sends a request (POST) to that endpoint with his email address. Devise then sends an email to Zed, with a confirmation link that contains a confirm_token. Zed clicks the link, which opens a page where he can enter a password. Once entered, he is logged in and an auth_token is stored against his user id. Subsequently he can use that auth_token to make further requests by passing the token in an Authorization header. The 'confirm_token' is throw away (you can set it to auto-expire after a given time period).
Obviously this requires Zed to manually create his account and login. Even if you setup a 3rd party 'developer program' you still need those developers to sign-up and generate tokens for them that they can pass in requests to your api. All of this should of course be done over https. Devise provides almost all of this capability out of the box.
secured?
HTTPS helps with the 'sniffing' aspect. The method above is secure, since only people who provide an email account they have access to can create accounts and get tokens that they can then user for later requests. However, you could use mobile phone number/sms as a second factor (google 2-factor authentication).
Without authenticaion - well, sort of
The only other option I can think of is that you issue known users a 'signing key'. They sign (encrypt) their request with this key. Since the key should only be known to them and can only be decrypted by the server using the matching public key, the data can be sent over HTTP. If anyone sniffs it, they almost certainly cannot crack the key to see what the real data is. All they can really do is mimic the request and keep sending that same request to the server repeatedly in a DOS attack.
But you still have to solve the problem of how do you verify WHO you are giving keys to - ie you still need to verify who Zed is somehow. Do you plan to do that offline and then email that 'verified' individual their private key? Using RoR, I still recommend sticking with Devise as most of the grunt work is done for you already.

Enabling OAuth support in Square Connect

I have an application that currently integrates into my merchant account using my access token. Early discussion with neighborhood merchants indicates some positive interest. I want to integrate OAuth support so that I can try to get traction with those merchants.
Though https://docs.connect.squareup.com/api/connect/v1/#navsection-oauth has information, I seek some additional clarification.
(i) Access using https redirect-url is denied at Square Connect Authorize has an answer "By default the OAuth flow is disabled for applications which is why you are seeing the "Authorization not allowed" failure. If you wish to enable OAuth flow for your application then you need to contact Square." #SquareConnectSupport: I have sent an email to Developer#Square, please let me know what else do I do.
(ii) Here is how I think it will work - the OAuth integration (Please confirm)
User types in browser say "mysnow.com/square"
The Handler at "mysnow.com/square" allows user to type in an ID this ID is local to mysnow
Then the Handler at "mysnow.com/square" directs the merchant to https://connect.squareup.com/oauth2/authorize along with my application id, permissions and redirect url.
The handler then receives a notification code with AuthZ Code at the redirect URL previously provided.
Next the handler obtains the Access token (using the AuthZ code)
Finally, the handler then saves the ID, the AuthZ code , the relevant Access Token and the date/time stamp (when the token was obtained) as a tuple in a safe data store.
(iii) Using the Access Token
When there is need to access merchant data of given ID, then use the ID to get the Access Token. Use this Access Token to manage the permitted data (based on permission)
Renew the access token periodically.
​(iv) For testing purposes, I create few test/dummy merchants?​ Or do you have dummy merchant accounts that I can use for testing.
You can authorize up to ten merchants through the OAuth flow without approval from Square, which should be enough to get your integration running and tested. If you would like to make it more broadly available, you will need to contact Square about getting the app in the Square App Marketplace.
That looks essentially correct. The best practice for OAuth is something like this:
Merchant visits your landing page (e.g. mysnow.com/square) and clicks an action to start using your square integration.
Merchant's browser is redirected to the OAuth page (https://squareup.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&scope=LIST_OF_OAUTH_SCOPES_YOU_NEED)
Merchant authorizes your application to access their data and is redirected back to your site. In the URL is an authorization code
Your backend makes an API call to Square to exchange the authorization code for an access token. It then uses that access token to look up information about the merchant and pre-populate fields of your signup form (e.g. you can get name, email, etc)
With a partially populated signup form on your site, merchant is prompted to complete their registration with your service.
There isn't really a way to create "dummy" merchants, but you can sign up for multiple merchant accounts with the same identity information, as long as you use a different email for each one. If you have GMail, you can do "you+someword#gmail.com" and the mail will be redirected to "you#gmail.com", so you don't need to create a bunch of email accounts to have unique email addresses.

Resources