Calling yahoo request_auth endpoint for OIDC SSO yields 'uh oh' - yahoo-oauth

I'm trying to login a user to yahoo using an OIDC RP using a redirect like this:
https://api.login.yahoo.com/oauth2/request_auth?response_type=code&client_id=(snip)&state=001520551248694Xjr6KF2IV&redirect_uri=https%3A%2F%2Fmyhostname.com%3A9444%2Foidcclient%2Fredirect%2FRP&scope=openid
After a successful login, the user gets this from yahoo:
Uh oh Looks like something went wrong. Please try again later.
I don't get the consent screen and I never get a redirect back. My initial redirect to yahoo for the login is the last thing that I can see in my trace.
I saw in another post that the redirect must match my YDN app's callback domain. The hostname in my redirect does match my callback domain. However, the value for the redirect parameter does not match since my uri is not just https:// (hostname).
Is there some way that I can find out what the 'something' is that went
wrong so that I can try to fix it?
If it is the redirect URI, how do I go about getting in touch with yahoo to find out if it is possible to have them support full uris?
-- The redirect uri should be a uri, not just a hostname (which is a urn). YDN wouldn't accept a port and it wouldn't accept a path.
-- Our runtime, and therefore our customers, cannot interoperate with yahoo if actual uris are not supported for the redirect_uri.
Ultimately what I'm trying to do is document how our customers can configure our RP to work with yahoo's OP and I can't make it work. Am I doing something that is obviously incorrect? (besides the redirect)

Related

Can't authenticate google app to read email [duplicate]

On the website https://code.google.com/apis/console I have registered my application, set up generated Client ID: and Client Secret to my app and tried to log in with Google.
Unfortunately, I got the error message:
Error: redirect_uri_mismatch
The redirect URI in the request: http://127.0.0.1:3000/auth/google_oauth2/callback did not match a registered redirect URI
scope=https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email
response_type=code
redirect_uri=http://127.0.0.1:3000/auth/google_oauth2/callback
access_type=offline
approval_prompt=force
client_id=generated_id
What does mean this message, and how can I fix it?
I use the gem omniauth-google-oauth2.
The redirect URI (where the response is returned to) has to be registered in the APIs console, and the error is indicating that you haven't done that, or haven't done it correctly.
Go to the console for your project and look under API Access. You should see your client ID & client secret there, along with a list of redirect URIs. If the URI you want isn't listed, click edit settings and add the URI to the list.
EDIT: (From a highly rated comment below) Note that updating the google api console and that change being present can take some time. Generally only a few minutes but sometimes it seems longer.
In my case it was www and non-www URL. Actual site had www URL and the Authorized Redirect URIs in Google Developer Console had non-www URL. Hence, there was mismatch in redirect URI. I solved it by updating Authorized Redirect URIs in Google Developer Console to www URL.
Other common URI mismatch are:
Using http:// in Authorized Redirect URIs and https:// as actual URL, or vice-versa
Using trailing slash (http://example.com/) in Authorized Redirect URIs and not using trailing slash (http://example.com) as actual URL, or vice-versa
Here are the step-by-step screenshots of Google Developer Console so that it would be helpful for those who are getting it difficult to locate the developer console page to update redirect URIs.
Go to https://console.developers.google.com
Select your Project
Click on the menu icon
Click on API Manager menu
Click on Credentials menu. And under OAuth 2.0 Client IDs, you will find your client name. In my case, it is Web Client 1. Click on it and a popup will appear where you can edit Authorized Javascript Origin and Authorized redirect URIs.
Note: The Authorized URI includes all localhost links by default, and any live version needs to include the full path, not just the domain, e.g. https://example.com/path/to/oauth/url
Here is a Google article on creating project and client ID.
If you're using Google+ javascript button, then you have to use postmessage instead of the actual URI. It took me almost the whole day to figure this out since Google's docs do not clearly state it for some reason.
In any flow where you retrieved an authorization code on the client side, such as the GoogleAuth.grantOfflineAccess() API, and now you want to pass the code to your server, redeem it, and store the access and refresh tokens, then you have to use the literal string postmessage instead of the redirect_uri.
For example, building on the snippet in the Ruby doc:
client_secrets = Google::APIClient::ClientSecrets.load('client_secrets.json')
auth_client = client_secrets.to_authorization
auth_client.update!(
:scope => 'profile https://www.googleapis.com/auth/drive.metadata.readonly',
:redirect_uri => 'postmessage' # <---- HERE
)
# Inject user's auth_code here:
auth_client.code = "4/lRCuOXzLMIzqrG4XU9RmWw8k1n3jvUgsI790Hk1s3FI"
tokens = auth_client.fetch_access_token!
# { "access_token"=>..., "expires_in"=>3587, "id_token"=>..., "refresh_token"=>..., "token_type"=>"Bearer"}
The only Google documentation to even mention postmessage is this old Google+ sign-in doc. Here's a screenshot and archive link since G+ is closing and this link will likely go away:
It is absolutely unforgivable that the doc page for Offline Access doesn't mention this. #FacePalm
For my web application i corrected my mistake by writing
instead of : http://localhost:11472/authorize/
type : http://localhost/authorize/
Make sure to check the protocol "http://" or "https://" as google checks protocol as well.
Better to add both URL in the list.
1.you would see an error like this
2.then you should click on request details
after this , you have to copy that url and add this on https://console.cloud.google.com/
go to https://console.cloud.google.com/
click on Menu -> API & Services -> Credentials
you would see a dashboard like this ,click on edit OAuth Client
now in Authorized Javascript Origins and Authorized redirect URLS
add the url that has shown error called redirect_uri_mismatch i.e here it is
http://algorithammer.herokuapp.com , so i have added that in both the places in
Authorized Javascript Origins and Authorized redirect URLS
click on save and wait for 5 min and then try to login again
This seems quite strange and annoying that no "one" solution is there.
for me http://localhost:8000 did not worked out but http://localhost:8000/ worked out.
This answer is same as this Mike's answer, and Jeff's answer, both sets redirect_uri to postmessage on client side. I want to add more about the server side, and also the special circumstance applying to this configuration.
Tech Stack
Backend
Python 3.6
Django 1.11
Django REST Framework 3.9: server as API, not rendering template, not doing much elsewhere.
Django REST Framework JWT 1.11
Django REST Social Auth < 2.1
Frontend
React: 16.8.3, create-react-app version 2.1.5
react-google-login: 5.0.2
The "Code" Flow (Specifically for Google OAuth2)
Summary: React --> request social auth "code" --> request jwt token to acquire "login" status in terms of your own backend server/database.
Frontend (React) uses a "Google sign in button" with responseType="code" to get an authorization code. (it's not token, not access token!)
The google sign in button is from react-google-login mentioned above.
Click on the button will bring up a popup window for user to select account. After user select one and the window closes, you'll get the code from the button's callback function.
Frontend send this to backend server's JWT endpoint.
POST request, with { "provider": "google-oauth2", "code": "your retrieved code here", "redirect_uri": "postmessage" }
For my Django server I use Django REST Framework JWT + Django REST Social Auth. Django receives the code from frontend, verify it with Google's service (done for you). Once verified, it'll send the JWT (the token) back to frontend. Frontend can now harvest the token and store it somewhere.
All of REST_SOCIAL_OAUTH_ABSOLUTE_REDIRECT_URI, REST_SOCIAL_DOMAIN_FROM_ORIGIN and REST_SOCIAL_OAUTH_REDIRECT_URI in Django's settings.py are unnecessary. (They are constants used by Django REST Social Auth) In short, you don't have to setup anything related to redirect url in Django. The "redirect_uri": "postmessage" in React frontend suffice. This makes sense because the social auth work you have to do on your side is all Ajax-style POST request in frontend, not submitting any form whatsoever, so actually no redirection occur by default. That's why the redirect url becomes useless if you're using the code + JWT flow, and the server-side redirect url setting is not taking any effect.
The Django REST Social Auth handles account creation. This means it'll check the google account email/last first name, and see if it match any account in database. If not, it'll create one for you, using the exact email & first last name. But, the username will be something like youremailprefix717e248c5b924d60 if your email is youremailprefix#example.com. It appends some random string to make a unique username. This is the default behavior, I believe you can customize it and feel free to dig into their documentation.
The frontend stores that token and when it has to perform CRUD to the backend server, especially create/delete/update, if you attach the token in your Authorization header and send request to backend, Django backend will now recognize that as a login, i.e. authenticated user. Of course, if your token expire, you have to refresh it by making another request.
Oh my goodness, I've spent more than 6 hours and finally got this right! I believe this is the 1st time I saw this postmessage thing. Anyone working on a Django + DRF + JWT + Social Auth + React combination will definitely crash into this. I can't believe none of the article out there mentions this except answers here. But I really hope this post can save you tons of time if you're using the Django + React stack.
In my case, my credential Application type is "Other". So I can't find Authorized redirect URIs in the credentials page. It seems appears in Application type:"Web application". But you can click the Download JSON button to get the client_secret.json file.
Open the json file, and you can find the parameter like this: "redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]. I choose to use http://localhost and it works fine for me.
When you register your app at https://code.google.com/apis/console and
make a Client ID, you get a chance to specify one or more redirect
URIs. The value of the redirect_uri parameter on your auth URI has to
match one of them exactly.
Checklist:
http or https?
& or &?
trailing slash(/) or open ?
(CMD/CTRL)+F, search for the exact match in the credential page. If
not found then search for the missing one.
Wait until google refreshes it. May happen in each half an hour if you
are changing frequently or it may stay in the pool. For my case it was almost half an hour to take effect.
for me it was because in the 'Authorized redirect URIs' list I've incorrectly put https://developers.google.com/oauthplayground/ instead of https://developers.google.com/oauthplayground (without / at the end).
The redirect url is case sensitive.
In my case I added both:
http://localhost:5023/AuthCallback/IndexAsync
http://localhost:5023/authcallback/indexasync
If you use this tutorial: https://developers.google.com/identity/sign-in/web/server-side-flow then you should use "postmessage".
In GO this fixed the problem:
confg = &oauth2.Config{
RedirectURL: "postmessage",
ClientID: ...,
ClientSecret: ...,
Scopes: ...,
Endpoint: google.Endpoint,
}
beware of the extra / at the end of the url
http://localhost:8000 is different from http://localhost:8000/
It has been answered thoroughly but recently (like, a month ago) Google stopped accepting my URI and it would not worked. I know for a fact it did before because there is a user registered with it.
Anyways, the problem was the regular 400: redirect_uri_mismatch but the only difference was that it was changing from https:// to http://, and Google will not allow you to register http:// redirect URI as they are production publishing status (as opposed to localhost).
The problem was in my callback (I use Passport for auth) and I only did
callbackURL: "/register/google/redirect"
Read docs and they used a full URL, so I changed it to
callbackURL: "https://" + process.env.MY_URL+ "/register/google/redirect"
Added https localhost to my accepted URI so I could test locally, and it started working again.
TL;DR use the full URL so you know where you're redirecting
2015 July 15 - the signin that was working last week with this script on login
<script src="https://apis.google.com/js/platform.js" async defer></script>
stopped working and started causing Error 400 with Error: redirect_uri_mismatch
and in the DETAILS section: redirect_uri=storagerelay://...
i solved it by changing to:
<script src="https://apis.google.com/js/client:platform.js?onload=startApp"></script>
Rails users (from the omniauth-google-oauth2 docs):
Fixing Protocol Mismatch for redirect_uri in Rails
Just set the full_host in OmniAuth based on the Rails.env.
# config/initializers/omniauth.rb
OmniAuth.config.full_host = Rails.env.production? ? 'https://domain.com' : 'http://localhost:3000'
REMEMBER: Do not include the trailing "/"
None of the above solutions worked for me. below did
change authorised Redirect urls to - https://localhost:44377/signin-google
Hope this helps someone.
My problem was that I had http://localhost:3000/ in the address bar and had http://127.0.0.1:3000/ in the console.developers.google.com
Just make sure that you are entering URL and not just a domain.
So instead of:
domain.com
it should be
domain.com/somePathWhereYouHadleYourRedirect
Anyone struggling to find where to set redirect urls in the new console: APIs & Auth -> Credentials -> OAuth 2.0 client IDs -> Click the link to find all your redirect urls
My two cents:
If using the Google_Client library do not forget to update the JSON file on your server after updating the redirect URI's.
I also get This error Error-400: redirect_uri_mismatch
This is not a server or Client side error but you have to only change by checking that you haven't to added / (forward slash) at the end like this
redirecting URL list ❌:
https://developers.google.com/oauthplayground/
Do this only ✅:
https://developers.google.com/oauthplayground
Let me complete #Bazyl's answer: in the message I received, they mentioned the URI
"http://localhost:8080/"
(which of course, seems an internal google configuration). I changed the authorized URI for that one,
"http://localhost:8080/" , and the message didn't appear anymore... And the video got uploaded... The APIS documentation is VERY lame... Every time I have something working with google apis, I simply feel "lucky", but there's a lack of good documentation about it.... :( Yes, I got it working, but I don't yet understand neither why it failed, nor why it worked... There was only ONE place to confirm the URI in the web, and it got copied in the client_secrets.json... I don't get if there's a THIRD place where one should write the same URI... I find nor only the documentation but also the GUI design of Google's api quite lame...
I needed to create a new client ID under APIs & Services -> Credentials -> Create credentials -> OAuth -> Other
Then I downloaded and used the client_secret.json with my command line program that is uploading to my youtube account. I was trying to use a Web App OAuth client ID which was giving me the redirect URI error in browser.
I have frontend app and backend api.
From my backend server I was testing by hitting google api and was facing this error. During my whole time I was wondering of why should I need to give redirect_uri as this is just the backend, for frontend it makes sense.
What I was doing was giving different redirect_uri (though valid) from server (assuming this is just placeholder, it just has only to be registered to google) but my frontend url that created token code was different. So when I was passing this code in my server side testing(for which redirect-uri was different), I was facing this error.
So don't do this mistake. Make sure your frontend redirect_uri is same as your server's as google use it to validate the authenticity.
The main reason for this issue will only come from chrome and chrome handles WWW and non www differently depending on how you entered your URL in the browsers and it searches from google and directly shows the results, so the redirection URL sent is different in a different case
Add all the possible combinations you can find the exact url sent from fiddler , the 400 error pop up will not give you the exact http and www infromation
Try to do these checks:
Bundle ID in console and in your application. I prefer set Bundle ID of application like this "org.peredovik.${PRODUCT_NAME:rfc1034identifier}"
Check if you added URL types at tab Info just type your Bundle ID in Identifier and URL Schemes, role set to Editor
In console at cloud.google.com "APIs & auth" -> "Consent screen" fill form about your application. "Product name" is required field.
Enjoy :)

Not able to get irb console working with tumblr_client gem

I have very little experience with APIs which is something that I'm trying to change so I'm trying to get started with the Tumblr api. I've installed the tumblr_client gem (documentation here) and am following the instructions. I've created an application on a new Tumblr account and have the necessary OAuth information (consumer_key, consumer_secret, ect.) Actually getting it to do something is proving difficult, so like a good little programmer I'm trying to get the console going to explore a bit.
This requires a bit of setup, so I'm following the instructions here:
The first time that you go to use the irb console, if you have no
.tumblr file, it will walk you through the process of generating one.
You will be prompted for your consumer_key and consumer_secret (which
you can get here: http://www.tumblr.com/oauth/register) and then sent
out to the site to verify your account. Once you verify, you will be
redirected to your redirect URL (localhost by default) and copy the
oauth_verifier back into the console. Then you're all set!
I'm prompted for my key and secret, then I go to the URL where I'm supposed to give authorization. Tumblr gives me a popup which reads "Is it alright for this application to access some of your data and make posts to your account? You are logged in as example#example.com" and the options to cancel or allow. I hit allow and it just takes me into the account itself, at no point am I ever given any kind of verification code that I can put in to get the console working.
At this point I'm stuck and can't go any further so I'm activating the network. Any ideas as to where I'm going wrong?
Did you specify a redirect or callback url at any point in the oauth config process? It's probably done on tumblr's API website. This url would be your app's endpoint to which Tumblr sends a request to with the user's data. By the way, oauth can sometimes be confounding to set up. You won't be able to use localhost as a callback url, for example, though you can get a temporary domain name with a free local tunneling app.
edit To go into more detail on some of these points ...
callback url: To reiterate, this cannot be localhost. Setting the correct callback url will get you unstuck from your current predicament. Instead of redirecting to the tumblr homepage, you want the confirmation page to redirect to your app. Anyway, I think you're totally sensible to want to test it out before you deploy. But unless you deploy or use a local tunnel, your local application doesn't actually have a URL that can be reached from anywhere except your computer.
local tunnelling services: ngrok, localtunnel. To give an example with ngrok: Say you have a Rails server running on port 3000. Then in another terminal you run ngrok 3000 and you get a url which exposes your local server to the real internet. Note that this changes every time you restart ngrok (unless you pay them). In your application, you should make a unique route for the callback. Say you have a route which matches /oauth_callback to the oauth_callback controller action. Then the route you'd provide as your callback url would be http://MY_CUSTOM_NAME.ngrok.com/oauth_callback.
The controller action: I don't specifically know how Tumblr sends user data to the callback. Perhaps the information is in the headers or maybe it's in the body. It might be JSON or XML. Whatever it is, you can explore the data by placing a breakpoint in your controller action. You can inspect the params, headers, etc. I'd expect that they'd give you some token credentials and probably a user name/email as well.

When authenticating a user with OAuth 2.0 how does the redirect URL know what user they belong to?

I'm new to web development and trying to get my feet wet by building a web app that uses Google APIs. I was reading Google's documentation on using OAuth 2.0, but the redirect URL bit has me a bit confused. According to the example here a successful authentication will send a response to
{redirect_url}?state=/profile&code={auth_code}
The response URL doesn't specify a user and neither does the response load as far as I know. How does the redirect URL endpoint know which user is tied to the authorization code it just received?
There was a very similar question here, but the answers focus on passing query parameters to the redirect URL. I'm not trying to do that. I want to understand how the redirect endpoint associates an OAuth response to a particular user. Note that I'm pretty new to all of this, so my confusion might stem from not understanding how HTTPS calls work or something similar.
A notable detail is when your redirect URL receives a response with code, it is the Google authorization server that redirect user's browser to your server. So it's user's browser that send a request to your server with code.
In other word, actually, you question is: "When your server receives many requests from many users, how do you know which user a request comes from"
I think you need to learn something about session or cookie which allows
HTTP to become stateful.

Downloading file via HTTPS using QNetworkAccessManager: How to authenticate?

The general answer you can find everywhere is to use the Signal authenticationRequired(QNetworkReply*, QAuthenticator*), then fill the login credentials into the given QAuthenticator object.
However, this does not work in my case as that signal is never emitted. Reason: The server does not return an authorization failure but redirects me to a login page instead. So my program will just download that page.
I have found out how to catch this by checking the attribute QNetworkRequest::RedirectionTargetAttribute of the QNetworkReply.
So I can detect the redirection and ask the user for auth info.
But... where do I go from there? How do I set the authentication data? Can I manually set a QAuthenticator to my QNetworkRequest or my QNetworkAccessManager? I didn't find a way to do that anywhere, just via the above-mentioned signal/slot mechanism which does not work because it does not trigger.
Any help would be greatly appreciated!
From documentation,
http://qt-project.org/doc/qt-5/qauthenticator.html
QAuthenticator supports the following authentication methods:
Basic
NTLM version 2
Digest-MD5
Since you are getting redirected to a login page, and you haven't indicated if any of the above authentication methods even works, I will assume that it does not because things like Basic authentication is sent on every request to the server. Login pages generally authenticate the client and use some sort of a cookie for future authentication. To do this,
Detect login page
Pass proper credentials to the server (based on what the form wants)
In the QNetworkReply to the login page, look for cookies (Set-Cookie headers).
Pass the relevant cookies back with your requests.
If it works, you are no longer redirected to login page.
For information on cookies, you can get overview via Wikipedia, but for implementation, you need to look at the RFC 6265,
If this is incorrect, and you can use basic authentication, then that information is passed in the URL itself. Set username and password in your QUrl and if it works, you will not be redirected. http://qt-project.org/doc/qt-5/qurl.html#setPassword

How to add multiple redirect URIs for Google OAuth 2?

I am trying to make Google OAuth 2 authentication work with a toy app I am running on my computer (at localhost:8080) using Social Auth for Java.
However when my app connects to Google to authenticate the user, Google responds with this error page:
My app, named "My Hobby App", is configured in the Developer Console as such:
In the Google OAuth 2 docs, it is specified that:
redirect_uri: One of the redirect_uri values listed for this project
in the Developers Console.
Determines where the response is sent. The
value of this parameter must exactly match one of the values listed
for this project in the Google Developers Console (including the http
or https scheme, case, and trailing '/').
I have a couple of questions:
How can I add multiple redirect_uris to my app?
Why is Google identifying my app as "Project Default Service Account" rather than "My Hobby App"?
It's actually easier than you think, unfortunately, it took me a couple of hours to figure it out.
How can I add multiple redirect_uris to my app?
Normally when you add multiple links to something on Google or elsewhere you separate it by , or ; but with Redirect URIs you have to use a new line, it's actually not very intuitive. So when you press the Edit Settings button, you can add to the URI and/or Origins if you have a couple more links, separated by newlines (enter).
No need for complicated app configurations or new keys.
Why is Google identifying my app as "Project Default Service Account" rather than "My Hobby App"?
On your second question: You have to go to the "Consent Screen" tab to change your app info such as your PRODUCT NAME, HOMEPAGE, LOGO, etc.
This answer may not be an exact answer to the question, but I think this might help those who are using Google OAuth for the first time and are wondering why their multiple URIs are not being recognized.
We use the redirect URI at 2 places in the code. First time, while fetching the auth code and a second time, when exchanging this code for an access token.
In the Google docs, it is clearly mentioned that the response for the auth code request(1st request) will be sent to the redirect URI. So, if you make the request from an endpoint A and specify the rediredt URI as endpoint B, Google will send the auth code to endpoint B. This is clear and worked fine without any errors.
Coming to the second request, the documentation is somewhat ambiguous. The redirect_URI parameter is described as below:
redirect_uri: The URI that you specify in the API Console, as described
in Set a redirect URI.
This is where I made a mistake in understanding how this works. Following a similar approach to the first call, I used a third endpoint C and passed this endpoint C in the redirect_URI parameter while making the second call. I got a URI mismatch error although my endpoints B and C are specified in the API console.
The problem is that, unlike in the case of first call, the response to the second call comes to the same endpoint from where the request is made. I made a request in python like below:
r = requests.post(token_endpoint, params)
r has the response with the token.
I was getting a URI mismatch because, I am supposed to use the same redirect_URI in both the calls.
So, for a single OAuth request, we need to use a single redirect_URI.
But then, that brings up the question, why are multiple redirect_URIs allowed in the API console for a single app. I am assuming that if we need to make multiple pairs of authCode-token calls in the same app, we have the leeway of using multiple redirect_URIs.

Resources