email missing from Google OAuth 2.0 ID token - google-oauth

This is largely a reboot of this unanswered question. We allow Google Sign-In to our site and, for the most part, it works well. But everyday a small fraction of the ID tokens we obtain from Google after authentication (between, say, 1 and 5% of them) do not contain an email, even though we specify "email" scope during front-end authentication. It's not consistent from user to user, and we are not able to reliably reproduce it (even though it consistently happens at the frequency above).
Has any encountered similar behavior?

Related

How to create a permanent authentication token with Auth0?

I need to create a permanent identifying URL for each user, through which (by visiting it), they will be logged in.
For example:
User1: https://www.example.com/?userToken=gj56u45g64g56uy54g6uyg546
User2: https://www.example.com/?userToken=8o9k7ok9o89k7o9ko8k9o78k9
The functionality is similar how one would identify to an API, or click an email confirmation link, but it has to be permanent or at least with a very long duration, because it will be stored on an NFC chip.
How can I do this within Auth0? (or Oauth 2, because I think that's what they use?)
From some reading that I did, I did not seem to find a way to get a permanent token for a user, and those tokens that I could get, had a maximum life cycle of 24 hours, which is too short for the intended use.
I have done this fairly quickly in a custom way, but within Auth0 I am not sure how it's done.
I read about refresh tokens, but these it seems to me, will need to be written to the NFC chip every time, which I can't do.
When you authenticate, you are given an ID and access token.
You typically use the ID-token to create a long-lived session-cookie, that can live as long as you like. The ID-token is by design a pretty short-lived token, by default like 5 minutes in some systems.
If it is for an embedded system, then there also the device-flow, that is more suitable for devices with a limited UI https://auth0.com/device-flow
I doubt writing JWT tokens from an authorization service is the right approach, as you have to remember that these services typically change/rotate their signing keys, so tokens issued for 6 months ago, might not be accepted today. And for example in a compromise and they are forced to change all their signing-keys, then all your devices will be made useless.
Better approach is to write your own "key" into each device.

How do Facebook, Google, and many others keep me (securely) logged in for so long?

So I've been looking at creating a a website. How exactly has not been decided, but lets say I'm going to use a React.js single page application (SPA) that interacts with a REST API.
This is fine and all, but at some point I am going to have to log users into this site. In looking into this problem, I have learnt about OAuth's implicit (or authorization code without a secret) grant, which is what they claim should be used when dealing with authorization in SPAs. The reasoning behind this is that there is no way for them to securely store a client secret, and thus they should only be given access to relatively short lived access codes. This being true for client-side authentication and authorization in general.
The problem, of course, is that every time your access token expires you need your user to re-authorize, as you now have no way of refreshing this access token.
Despite this, websites like Google, Facebook and Github (among many others) seem to keep me permanently logged into their systems. Surely this means they are storing some sort of session ID permanently within the browser and thus this suffers the exact same problems as to why you shouldn't use client secrets in OAuth?
So how do they deal with this? Are they just, effectively, using very long lived access codes or session IDs and say "screw security"? I mean, Google force me to use short-lived access codes if I want to make an application that requests their data, so why do their own apps and website not suffer from this?

Authenticating QuickBooks API

I don't believe I need OAuth
Then again, what do I know
All I want to do is take someone's credit card information and charge them. I am not accessing other people's QuickBooks accounts (only my own) and I am not trying to access any other personal information other than what they input into my form. For this reason it seems absolutely asinine to think that I'd have to redirect them to intuit.com and force them through an OAuth prompt (what account would they even be authorizing? They probably don't have a QuickBooks account)
I've spent the last hour reading through QuickBook's API documentation and I've run in circles and found the whole thing utterly confusing. Every page which references a particular API endpoint makes no mention of authentication -- only the headers, query parameters, and request body that are expected. The API explorer does not show any form of authentication in their examples:
No basic auth header, nothing in the request body with an API token,.. nothing
Checking the console while hitting submit isn't any more helpful. The request gets sent to their back-end server where it does the real request:
It even includes "apikey", "apisecret", and "oauth" attributes in the body which are all empty -- it acts like the endpoint doesn't even NEED authentication.
Out of dumb curiosity I tried making the request with no authentication to see what would happen:
401 Not Authorized. So some authentication is needed. I continued to scour the docs and turned up nothing but page after page linking me back to OAuth and saying that I need to set up OAuth. Why do I need to set up OAuth to take a credit card number that was given to me and hand it to QuickBooks?
I even tried looking at their sample app. The "take the code for a test drive" (https://developer.intuit.com/v2/ui#/emulator?workflow=ecommerce) was utterly worthless. It only gave me some pseudo-code with zero idea for how to handle authentication:
I even looked at the actual code and don't see anywhere that they provide an API key or secret key.
I'm pretty much ripping my hair out at this point, so I think I need someone with experience to point me in the right direction.
I don't believe I need OAuth
You do.
For this reason it seems absolutely asinine to think that I'd have to redirect them to intuit.com and force them through an OAuth prompt
You misunderstand what OAuth is, and how it's used.
OAuth is used to get YOUR auth tokens so that YOUR COMPANY can authenticate to Intuit and identify itself so you can charge customer credit cards. YOU are redirected to Intuit's website to authenticate ONCE, and ONCE ONLY, and then NEVER AGAIN.
You store the tokens you get back from the one-time OAuth pop-up window process, and use those for all future HTTPS requests.
The end-user (i.e. your customer) is NOT redirected.
If you're familiar/used to something like Authorize.net or other web services, where you open a web browser and go to a website and copy a secret key/API token into your code... this is the exact same process except instead of you logging in and manually copy/pasting an API token/key, you're logging in and the OAuth process automatically gives you the API token/key programatically.

What credentials system should I use for an app where submissions to an API are anonymous?

I'm creating an app where user submissions (e.g. photo) are designed to be captured via crowdsourcing. The app connects to an API using an API key, and the app then submits the data anonymously.
We want to avoid the overhead of people creating user accounts and passwords.
However, it seems to me this is vulnerable to a the problem of the key getting revealed. The result is that spammy submissions could be made much more quickly via browser/wget HTTP requests. Because the app is installed on people's devices, it would take a long time for us to be able to withdraw a key and replace it with another.
The approaches to deal with this problem I can think of are:
Hope that the key stays secret. Not ideal from a risk perspective. Using HTTPS for the API endpoint would reduce this risk, but presumably the app could still be decompiled to reveal it (not that in practice anyone would really bother)
Store a fixed username and password in the app, and submit as that. That basically seems to run the same problem - if the credentials are leaked then this has the same problem as 1.
Require a first-run fetch of a token to auto-create a username and password. However, if the key is compromised then this is no more secure. Also, this means we end up with lots of junky usernames and passwords in our database that really don't mean anything.
Not considered desirable: force users to create a username/password. However, that then means a lot of messing around with accounts, and compromises the anonymity of submissions, meaning data protection implications.
Are there standard patterns dealing with this scenario?
The first time the app runs, it could get a random token from the server, store this, and use it on all subsequent requests. The server just checks that the token is one it produced itself. After each request, block the token for 5 minutes (or make a counter so 10 requests are ok but the 11th gets blocked, depending on your use case). When a token gets misused, block it, so the user will have to deinstall/reinstall your app, or, if he made a script to emulate the app, he'd have to re-register after every few posts (plus you can limit the numer of registrations per IP or something similar).
You can assume any fixed credentials will be compromised. A good attacker can and will reverse-engineer the client. On the flip-side, a username/password combo will compromise anonymity (and nothing is stopping a spammer from creating an account).
Honestly, this is a very difficult problem. The (inelegant) solution involves something like a captcha where you provide a problem that is difficult for a bot but easy for a human to solve (for the record, I think captchas are almost useless, although there have been some less annoying alternatives).
Alternatively, sites like Facebook use sophisticated algorithms to detect spam. (This is a difficult approach so I would not recommend it unless you have the manpower to dedicate to it).

is openid.claimed_id static?

I'm reading about Federated Login for Google Account Users to figure out how I can have a user log in to a web application using their Google Account.
So towards the end of the process, Google returns a Google supplied identifier which is appended as openid.claimed_id. This means the web application uses this identifier to recognize the user and allow access to application features and data. My question is, is this identifier static? Can I use this identifier to repeatedly id the same user?
Yes. Consider the openid.claimed_id value to be the username. Especially with Google, but this is true for any OpenID Provider that truly implements 'directed identity', don't consider this username to be correlatible with other web sites. Any other relying party besides your own web site will get a different claimed_id value for the same Google user, by design.
Also, be sure to treat this claimed_id as case sensitive.
The specific answer to your question is found in Googles OpenID API documentation:
The Google-supplied identifier, which has no connection to the user's actual Google account name or password, is a persistent value; it remains constant even if the user changes their Google user name and/or email address. This identifier is also a "directed identity", that is, Google returns a different value to each relying party. Google uses the request parameter openid.realm to recognize the relying party, so if the third-party application decides to change this value, all user identifiers will change.
In fact, I just ran into an instance where the google claimed_id had changed for my test user. I was coming to the end of implementing OpenID into my app, and for no apparently reason the claimed_id in the response data is had changed.
I've been testing with this account for the past couple weeks, and the claimed_id was the same this entire time, as expected. Then wham, changed! I looked at the response data many times to verify, and the underlying code to retrieve the data had not changed.
I'm not sure how to handle this at the moment, but I think this is going to throw me for a loop. After initial authentication, users register to the site (as you might expect) and setup a screen name. How are we to verify it is the same user if the claimed_id had changed? We certainly can't use email address, per best practices.
EDIT
Now I have pie in my face! I missed one little detail, that turned out to be a major detail. I change my development environment and was hosting on a different v-host. This effectively change the realm, and this will change the claimed_id response according to the docs.
This was a good lesson for me, as I was about to implement OID on a subdomain in which realm was being set automatically in my code. Now I saved myself a headache down the road, because I would not have been able to use the same user database across all other sub-domains without breaking identity.
updating realm
MORE INFO
Just as a side note - even if you are developing your OpenID solution for one of your subdomains, it might be prudent for you to specify realm to your top-level domain.
e.g., openid.realm = http://*.yourdomain.com
It will allow you to expand your sign-in page across all your subdomains and keep user identity across them.
(optional) Authenticated realm. Identifies the domain that the end
user is being asked to trust. (Example: "http://*.myexamplesite.com")
This value must be consistent with the domain defined in
openid.return_to. If this parameter is not defined, Google will use
the URL referenced in openid.return_to.