oauth 2 to authenticate users stopped working suddenly in all environments - windows

We have application on compute engine that is using oauth2(Using GCP credentials) to authorize users to access application and it was working all fine. Suddenly since last two days we are getting 401 not authorize message from google authenticator instead of access token.
Have verified that the service account is active and APIs access enabled on GCE.
We tried rotating GCP API credentials but that did not work, even one of the environment was allowing to login again but go broken again in the morning.
Here is the sequence of incidents:
User hit url to access web app
That redirects to -> google auth page, requesting user to login consent
Credential provided user and accepted by google.
Instead of providing authentication token google is giving message access denied.
Not sure which logs can give clear picture to see the errors.

If your App is External Facing but is still in test mode (not verified), the token will expire after 7 days (source)

Related

Unable to get the Bearer Token - Web Test, Performance Testing

I'm creating a Web Test in Visual Studio 2017 for Performance Testing. Our web application is an Azure with an AAD authentication frontend. It is the authenticating as a test user that is failing. While recording with VS or fiddler, I'm failing to playback the test again. I believe it is a token issue.
I'm able to see the Authentication Bearer Token in Location parameter of Response Header in the Browser. Example-
Request URL: https://login.microsoftonline.com/login.srf
Response Header:
Location: https://domain.fake.URL/login#id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IkhCeGw5bUFlNmd4YXZDa2NvT1UyVEhzRE5hMCJ9.eyJhdWQiOiIxZDYwOGIxOC04YjI2LTQ0MDktODg3ZC1mZmIzY2MxYzEwNDQiLC.....
However, I'm unable to get the Bearer Token in Visual Studio. I checked Visual Studio is making the same request with same parameter but in the response it's getting the below error not the token.
Location : https://domain.fake.URL/login#error=invalid_grant&error_description=AADSTS50008%3a+SAML+token+is+invalid.%0d%0aTrace+ID%3a+3c5c2728-f013-49e3-a91d-88a683210800%0d%0aCorrelation+ID%3a+f21fda63-6dc7-4b35-9b46-fc354cc4e8ea%0d%0aTimestamp%3a+2019-05-16+06%3a23%3a48Z&state=29ee5c1a-f49a-4358-be60-8f722f1e6e80
Instead of the token.
Is anyone faced similar issue? Thanks, guys.
When you recorded the test, it is likely you went through a federated sign-in process with your organization's on-premises AD FS. (This federated sign-in may have been transparent, as a series of redirects.) As part of this federated sign-in, your organization's AD FS will have issued a SAML token identifying the user to Azure AD. Azure AD will have then verified that SAML token, and since everything checked out, it issued it's own token to the application (the response with #id_token=...).
However, when you attempt to replay those steps later, the original SAML token issued by AD FS (during the original recording) has expired and is no longer valid. So instead of Azure AD redirecting back to your app with the expected ID Token, it redirects back to you app with the error about a bad SAML token.
You should be able to verify this by recording a fresh sequence of the sign-in, and replaying for the test immediately. You'll likely find that the test will pass at first, and then will eventually start failing again once the token expires.
The solution to this depends a lot on your test environment, your Azure AD and AD FS environment, and what specifically you're trying to load test. One option is to use a cloud-only dedicated test user, from a dedicated test tenant in Azure AD (you should not include any credentials for real users from your production environment in your tests). If part of what you're trying to validate includes the federated sign-in, then you should use a test instance of AD FS, and federate your test Azure AD tenant with this test AD FS.

Open ID Connect Session Management Access/Refresh Token vs Session iFrame

We have a web app in which we allow users to log into the app using any Open ID provider(e.g. Okta, Google, Facebook etc.). We want to implement the correct Open ID Connect prescribed methodology/workflow to keep the user logged into the site.
The existing implementation, looks at the expiry of the Access Token then if it's close to expiry uses a Refresh Token to get a new Access Token to keep the user logged in. I feel like this is wrong. When a user logs in to the web app, the Identity Token is used to Authenticate the identity of the user using the Authorization Code workflow. The Access Token and Refresh Token are stored on the server side. Periodically, the Refresh Token is used to get new Access Tokens to keep the user logged into the site. I believe this is a security risk because -
Imagine if a user is logged onto his OP account in a browser. He opens up Sky and is directly logged into MP because he’s already logged into MP. He then in a separate tab, logs out of his OP account. He will continue to be logged into MP for days on the basis of this Refresh Token/Access Token mechanism! Isn’t this a security risk?
If feel like the correct way to go about this is to use Session Management using iframes as prescribed here on OIDC -
https://openid.net/specs/openid-connect-session-1_0.html
For more context, when a user logs into our WebApp we pull data from the OP's UserInfo endpoint to create a profile within our WebApp and set permissions/roles within our app based on data sent over from the OP's UserInfo endpoint. We continue doing this periodically. For this purpose, I feel like using the Access Token(and using the Refresh Token to get new Access Token) to access the UserInfo API is correct because it conforms to the OAuth 2.0 concept of protecting/authorizing API/Resource endpoints using Access Tokens.
I want to know if this is indeed the correct way to manage how a user should be logged in when supporting Open ID Connect.
I think the first question is whether you want to bind the lifetime of an OpenID Connect provider Single Sign On session with the session of your application. You just want to authenticate a user using their OpenID Connect service. If I logout of Google, I expect to be logged out of GMail, but not a third-party application that used Google for authentication. Would you like to implement Single Sign Out as well?
But if I wanted to be logged out when you logout of the OpenID Connect provider, I would implement the OpenID Connect Session management. There is one thing good to be aware of when using iframes and cookies - browsers have an option to "Block third-party cookies" (that's how Chrome calls it), it's turned off by default, but as far as I know, it disables the SSO functionality when turned on.
I'm not sure why you request the userinfo endpoint periodically. If you just want to check whether the access token is still valid, you could also use the token introspection endpoint.
For security concerns, I would suggest you to read the OAuth 2.0 for Browser-Based Apps RFC. It recommends using the auth code flow with PKCE instead of the implicit flow. With the implicit flow, access tokens transported in redirect URLs stay in network and browser caches and can be used right away by an attacker. The auth code with PKCE needs a code_verifier (one-time secret) in order to be exchanged for tokens. So I would first check how the providers work with a configuration you choose and if it's even supported.

Alexa skill account linking with Google APIs credentials, problem refreshing token

I'm having some problems with the Alexa account linking authorization.
These are the steps I followed:
I got the credentials (client id, client secret...) from the Google Cloud Console
Setup on the Alexa Developer Console, using 'Auth Code Grant' as authorization grant type
Activated the skill on my Alexa application and successfully logged in with my Google account
Now I got the access token in the request, in handler_input.request_envelope.context.system.user.access_token
The problem is that the access token expires after one hour and Alexa does not manage the refreshment of the token.
What should I do to avoid having to ask my users to login every time after one hour? Should I use Implicit grant as authorization type? Should I get a refresh token somehow?
Additional info: it's a custom skill that connects to an AWS Lambda using Python3
While #pinoyyid's answer was correct, it didn't provide a solution so I'm posting one for future reference.
The problem was indeed that Amazon servers did not receive a refresh token from Google, thus making it impossible to refresh the access token after its expiration time of one hour.
Following this link and other Amazon forum posts, I got to a working solution.
Amazon Alexa developer console 'Account Linking' configuration:
Authorization grant type: Auth Code Grant
Authorization URI: https://accounts.google.com/o/oauth2/v2/auth?access_type=offline (even though the one from the google credentials was not v2, it shouldn't make a difference)
The access type is very important because, as documentation goes:
Set the [access_type] value to offline if your application needs to refresh access tokens when the user is not present at the browser. [...] This value instructs the Google authorization server to return a refresh token and an access token the first time that your application exchanges an authorization code for tokens.
Access Token URI: https://accounts.google.com/o/oauth2/token
Client ID & Secret: downloaded on Google Cloud Platform
Client Authentication Scheme: HTTP Basic
Domain List: google.com and googleapis.com
Default access Token Expiration Time: left empty
Now, after doing this and saving the configuration, be aware that you might not notice the change, as, from here:
When Alexa uses the refresh token to retrieve a new access token for an existing user, Alexa uses the access token URI that was configured at the time the user linked their account. Therefore, if you change the access token URI later, users who linked their accounts before continue to use the old URI for retrieving updated tokens. The users must unlink and re-link accounts to switch to the new access token URI.
So, in order to complete the procedure:
Deactivate your skill
Go to the Google third party applications that have access to your data and remove your Google Project associated
Reactivate your skill and login again (if done correctly it should ask you the permissions for the scope you specified in the Alexa developer console again
Done! after one hour you should re-try and it should have a renewed access token
Additional Info
I found that many suggested to retrieve the refresh token, I don't believe this is possible because, even if Google sends it, it's Amazon that stores it and uses it to refresh the access token.
EDIT:
This works fine for developing and testing but I discovered here that for publication purposes you must own the landing page that you redirect your users to. For me it was just necessary to create a simple HTML page hosted in a public S3 bucket that would redirect the request to the Authorization URI I wrote before, while the Access Token URI must remain the Google one.
Have you read https://developer.amazon.com/docs/account-linking/configure-authorization-code-grant.html ?
My guess is that the Refresh Token is missing because you have already auithorised the app. The RT is only issued once. Try going into https://myaccount.google.com/permissions?utm_source=google-account&utm_medium=web to revoke the permission and try again.

Windows Azure: AD app for external access throws error on token issue

I am trying to build an AzureAD access app. I have to enable this app for external tenants. I have enabled external access on this app and it is configured to use the Graph API also. I have tested the app in the tenant in which it was created and everything(auth+ graph api access) works. Now here is the flow for the external tenant
I take the external tenant user to the grant consent URL of my app, the user(who is an admin of the external tenant) grants the access and i get the correct response
Now i want to get the authorization token for this user, so i take the user through the normal Oauth process via
https://login.windows.net/common/oauth2/authorize
followed by
https://login.windows.net/common/oauth2/token/
At this point Azure throws the following error
{"error":"invalid_grant","error_description":"AADSTS50000: There was an error issuing a
token. AADSTS65005: No permission to access \u0027https://graph.windows.net\u0027
resource is configured for \u0027d2037ff7-24e4-4cac-8e5e-16e370b36238\u0027 application,
or it is expired or revoked.\r\nTrace ID: 472aa92f-35a2-4ed9-ab07-
12488cc9e6f5\r\nCorrelation ID: b163dde5-eac5-4c82-99ad-0e1100487cb9\r\nTimestamp: 2013-
09-23 05:28:41Z","error_codes":[50000,65005],"timestamp":"2013-09-23
05:28:41Z","trace_id":"472aa92f-35a2-4ed9-ab07-12488cc9e6f5","correlation_id":"b163dde5-
eac5-4c82-99ad-0e1100487cb9"}
Why this error even when the app has been granted access. I tried to lookup the STS errors
but found no explanation. Any ideas?
[update]
SAML process continues to work for the external tenant however i.e I can use the app for SAML(SSO) login for this external tenant. The problem only seems to be coming for getting access to the graph API.
Try adding &prompt=consent or &prompt=admin_consent to the full authorize URL to re-request the user consent. My experience has been that the consent will be randomly revoked (maybe a bug) and will not ever be automatically re-requested (definitely a bug).

Google API OAuth2: handle invalid token

I have a tricky case while playing with OAuth2.
Starts by asking authentification to the user. He grants access, store the credentials in a store (DB, GAE Datastore, etc.).
Go to your Authorized Access in your Google's profile and revoke the
app
Go back to the app, launch an action which leads to API call (tested
with Drive API)
App is retrieving credentials from store. Test credentials validity
(not null and invalid property is False)
Call the API
Retrieve a 401, Unauthorized exception.
How can I detect that the credentials are invalid BEFORE effectively calling the API?
Maybe it is the way to works with credentials?
Thanks for your help.
What credentials are you storing? Access token? Refresh token?
Consider using the tokeninfo endpoint, https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=
Before using the access_token, call [tokeninfo] in GoogleAPI first (always, if it's a fresh access_token even). I wasted some hours to solve this issue.
My workflow for a Windows application:
oAuth2 -> access_token* (* - not validated)
GoogleAPI.tokeninfo with [access_token*] -> "ok" or "invalid"
if "ok" - using for requested permissions

Resources