Handling OAuth as a part of a REST Create Request - rest

I am implementing a REST API that allows the user to create an object called channel that represents their Youtube Channel. Now as a part of this request I need the user to Authorize the request with Google's OAuth service and provide the oauth token and token secret.
What is the best way to implement this kind of API. I am using OAuth 1.0a.

Related

How do I get an OpenID Connect ID token from GitHub's API to implement social login?

Background
I'm trying to implement social login using GitHub accounts and OpenID Connect, but I can't figure out what GitHub endpoints I'm supposed to:
redirect the user to and
POST the authorization code to
...to get back an ID token, or if I already have the right endpoints but the wrong parameters.
I've been following/adapting this guide to implementing social login with OpenID Connect (which uses Google as the Identity Provider rather than GitHub) and referring to the "OAuth 2.0 web application flow" GitHub docs page to try to understand how I need to adapt the guide to work with GitHub (i.e. what GitHub endpoints and parameters I need to use).
My problem
When I POST the authorization code to https://github.com/login/oauth/access_token (the URL specified in GitHub's docs) I get back an access token and a refresh token but no ID token. I suspect this is because the GitHub docs page is meant to be used to implement a plain (non-OpenID Connect) OAuth 2.0 flow.
What I've tried
I did a lot of Googling and found these 2019 slides from PragmaticWebSecurity.com that say I need to initially redirect the user to a different endpoint (https://github.com/openid-connect/auth rather than https://github.com/login/oauth/authorize, see slide 29), but when I try to do that, I get a 404 error from GitHub. I tried emailing the guy who created those slides to ask if the endpoint had changed, but he hasn't responded to me.
These are my guesses at what the answer to my question is:
GitHub doesn't support OpenID Connect / it isn't possible to get back an ID token; I need to just use the access token to query the API to get back whatever information I need about the user.
This would explain why I can't find any mention of social login with OpenID Connect in GitHub's docs.
I have the right endpoint (https://github.com/login/oauth/access_token), but I'm missing some required parameter to get back an ID token.
I have the wrong endpoint.
I contacted GitHub Support and got an official response: Their API doesn't support OpenID Connect for social login.
Here's their full response:
Hi Nathan,
Thanks for reaching out!
GitHub OAuth flow does not currently support the OpenID connect
functionality. You'll need to use the OAuth 2.0
https://docs.github.com/en/developers/apps/building-oauth-apps/authorizing-oauth-apps
Regards,
Oluwaseun GitHub Support
So, until they add support for OpenID Connect, you can refer to this write-up I did on how to implement social login using OAuth 2.0:
How do I implement social login with GitHub accounts?
From your guesses 1) and 2).
github oauth apps currently do oauth2 not oidc, it kind of stares in your face with the name, but I missed it as well.
I'll leave this for others researching this.
oauth2 != oidc, Depending on your use case you might have a client library that supports both, the config will look the same, but the response is different and needs to be handled correctly.
As per OpenID specification, I think you'll need to authenticate with OAuth2
The primary extension that OpenID Connect makes to OAuth 2.0 to enable
End-Users to be Authenticated is the ID Token data structure. The ID
Token is a security token that contains Claims about the
Authentication of an End-User by an Authorization Server when using a
Client, and potentially other requested Claims.
...
The OpenID Connect protocol, in abstract, follows the following steps.
The RP (Client) sends a request to the OpenID Provider (OP).
The OP authenticates the End-User and obtains authorization.
The OP responds with an ID Token and usually an Access Token.
The RP can send a request with the Access Token to the UserInfo Endpoint.
The UserInfo Endpoint returns Claims about the End-User.
Then you should be able to forward through OpenID the token, once you have set up the trust between the Authentication provider and the Autorization provider.

How should I use SAML login with a REST API + SPA app?

I want to use SAML login for a single web application with a REST API. How should I do this? Usually, say with OAuth, lets use Google/Firebase as an example:
SPA calls Google to login. Google returns a Google ID token
SPA can call Server with Google ID token which server can verify with Google and return an access token for use with the application
Firstly is this correct or did I get something wrong so far?
But with SAML, from what I can see, its user is redirected to SAML IDP, SAML IDP then redirects user to a server assertion URL. Because there is this redirect, how do I use it in the context of REST? I am unfamiliar with SAML, but I dont see a token. The server just gets an "assertion" with the user information?
Here is the sequence of events which happen when the application is using SAML for the authentication:
server should send a response to the client with the URL to SAML IDP.
client application redirects the browser to SAML IDP (1).
After successful authentication, SAML server sends response with the redirect back to the client. The browser automatically posts the HTML form SAML server to your server.
After validating SAML assert and successful authorization (you can use user's information or other attributes to authorize the user to use your application), your server should generate a token that now can be used by the client application.
This is a basic scenario.
See spirng-saml project here, you can try and play with the sample web application.
https://projects.spring.io/spring-security-saml
SAML assertion is an equivalent of id_token in OpenID Connect 1.0 that Google uses. There is no access_token in SAML. SAML is an authentication protocol.
OAuth 2.0 that uses access_tokens is an authorization protocol. That is why it provides an access_token to authorize access to your REST API.
OpenID Connect is an extension of OAuth 2.0 that supports user authentication in addition to API authorization and introduces id_tokens that contain user information.
One of the options to use SAML in your Single Page Application with REST API is to host them at the same domain. In this case you can:
Get an assertion from SAML Identity Provider.
Verify it (format, signature, lifetime, etc) on the server side.
Return a session cookie in the response to set it in the browser.
Each request to the REST API will come with a session cookie authorizing access to it.

How should my api handle login via auth0?

I'm trying to learn how to utilize auth0 to handle user authentication for an api I am currently creating.
My api has two endpoints:
Login endpoint: /api/login
Request access token endpoint: /api/auth?code={code}
Here the authentication flow is:
User goes to the login endpoint of my api.
User is redirected to auth0 ui.
User inputs their login credentials.
Auth0 redirects back to /api/auth where a request for an access_token is made using the login code.
Firstly, is my understanding the Oauth authentication flow correct? If so, how best should my api handle the initial login redirect to auth0?
Because at the moment when I hit up /api/login from the front-end ui it just returns the html of the login page at auth0. Should I instead return a 302 with the redirect url or is it possible to create an endpoint where the user inputs the username & password via my api and avoids the redirect?
---update---
After a user has authenticated via auth0 they receive a access_token and id_token which should my api use to verify the user is who they say they are?
Not sure if my understanding is correct but I belive that my frontend ui is the OAuth client application and my API service is an OAuth resource server. As such does my api need to call out to auth0 /userinfo to verify the user?
Assuming you are trying to protect an end-user application (your question wasn't clear on that), my understanding is if you are using Auth0, you likely won't need an /api/login and api/auth API. If you are using Auth0 you can get those things during your authentication via Auth0.
I would say your APPLICATION (not API) would redirect the user to the Auth0 login endpoint. You would do that by incorporating the Auth0 SDK of choice, depending on what you're building. For example, if you're building a web app, you may choose to incorporate auth0.js and call webAuth.authorize() to trigger the login. During that login, if you have configured an API within Auth0, and you provide the proper Scope and Audience during your login, your response will return an API token.
Then your user is in a state on the client side where you are logged in, and you have a token. You can then provide that token to your API, and your API can validate that token as needed. Auth0 also has various libraries for token validation (like this spring security one, for example).
Lastly, the question on which oAuth flow to use, that also depends on what type of app you're protecting. There are again Auth0 docs to help. The flow depends on if you're building a server-side web app, a SPA, a native app, etc. Your question was a little confusing, and it sounded a bit like you are building an API and want to protect that. If there is no client-side app (only machine-to-machine API calls), then you wouldn't be dealing with HTML and login pages. You'd likely be getting into the Client Credentials flow, which last I checked was only included for Enterprise Auth0 users.

Web API authorization with ACS with Facebook authentication token

I have a web api which I want to secure using ACS, but I want to use ACS for authorization only. The flow I want is:
The user is redirected by the app to authenticate with Facebook and
the app receives a Facebook token.
The app sends a request to ACS with the Facebook token and receives
a new token, which he can use to access the API.
The user calls the API and passes the token received from ACS as
authentication/authorization for the API.
Is this flow possible? How do I set this up on the ACS side and the API side?
I already have the Facebook authentication working in the app. I would like to leverage the token I am already getting in order to call the API.

REST API for website which uses Facebook for authentication

We have a website where the only way to login and authenticate yourself with the site is with Facebook (this was not my choice). The first time you login with Facebook, an account gets automatically created for you.
We now want to create an iPhone application for our site and also a public API for others to use our service.
This question is about how to authenticate with our website from the app/API and is broken into 2 parts:
What is the correct way to handle REST authentication from an API to a website which only uses Facebook OAuth as an authentication method?
I have read and researched a lot about standard methods of authentication for REST API. We can't use such methods as Basic Auth over HTTPS, as there are no credentials for a user as such. Something like this seems to be only for authenticating applications using the API.
Currently, the best way I can think is you hit an /authorize end-point on our API, it redirects to Facebook OAuth, then redirects back to the site and provides a 'token' which the user of the API can use to authenticate subsequent requests.
For an official application that we create, we wouldn't necessarily need to use the public API in the same way. What would be the best way then to talk to our website and authenticate users?
I understand (I think) how to authenticate 3rd-party applications that are using our API, using API (public) keys and secret (private) keys. However, when it comes to authenticating the user who is using the app, I am getting rather confused about how to go about it when the only way we have to authenticate a user is Facebook.
I feel like I'm missing something very obvious, or don't fully understand how public REST APIs should work, so any advice and help would be greatly appreciated.
UPDATE: see below
I've been thinking hard about this question too. It's not entirely clear to me yet but here's the route I am thinking of going. I am creating a REST API an my users only auth with Facebook connect.
On the CLIENT:
Use the Facebook API to login and get an OAUTH2 code.
Exchange this code for an access token.
In every call to my custom API I'll include the Facebook user id and the access token.
On the API (for every method that requires user authentication):
Make a request to the /me Facebook graph using the access token from above.
Verify that the Facebook user id returned matches the user id passed to my API from above.
If the access token has expired additional communication is required.
I have yet to test this. How does it sound?
--- Update: July 27th, 2014 to answer question ---
I only use the above exchange once upon login. Once I determine which user is logging in, I create my own access token, and that token is used from that point going forward. So the new flow looks like this...
On the CLIENT:
Use the Facebook API to login and get an OAUTH2 code.
Exchange this code for an access token.
Request an access token from my API, including the Facebook token as a parameter
On the API
Receive access token request.
Make a request to the /me Facebook graph using the facebook access token
Verify that the Facebook user exists and match to a user in my database
Create my own access token, save it and return it to the client to be used from this point forward
This is my implementation using JWTs (JSON Web Tokens), basically similar to Chris' updated answer. I have used Facebook JS SDK and JWT.
Here's my implementation.
Client: Use Facebook JS SDK to log in and get the access token.
Client: Request JWT from my API by calling /verify-access-token endpoint.
MyAPI: Receives access token, verify it by calling /me endpoint of Facebook API.
MyAPI: If access token is valid, finds the user from database, logs in the user if exist. Create a JWT with required fields as payload, set an expiry, sign with the secret key and send back to the client.
Client: Stores the JWT in local storage.
Client: Sends the token (the JWT from step 5) along with the request for the next API call.
MyAPI: validate the token with the secret key, if token is valid, exchange the token for a new one, send it back to the client along with the API response. (No external API calls for verification of the token here after) [if the token is invalid/expired request client to authenticate again and repeat from 1]
Client Replaces the stored token with the new one and use it for the next API call. Once the token expiry is met, the token expires revoking access to API.
Every token is used once.
Read more answers about security and JWT
How secure is JWT
If you can decode JWT how are they secure?
JSON Web Tokens (JWT) as user identification and authentication tokens
I am trying to answer the same question and have been going through a lot of reading recently...
I won't have "the" answer but things are getting a little clearer for me. Have you read the comments in the article you mentioned? I found them really interesting and helpful.
As a result, and in the light of how things have evolved since the first article has been written, here's what I think I'll do:
HTTPS everywhere — this allows you to forget about HMAC, signing, nonce, ...
Use OAuth2:
When authentication requests come from my own apps/website, use this 'trick' (or a variation of it) described in a reply to the article mentioned before.
In my case, I have two types of users: those with classic login/password credentials and those who have signed up with Facebook Connect.
So I'd provide a regular login form with a "Login with Facebook" button. If the user logs in with his "classic" credentials, I'd just send these to my OAuth2 endpoint with a grant_type=password.
If he chooses to log in via Facebook, I think that would be a two-steps process:
First, use Facebook iOS SDK to open an FBSession
When that's done and the app is given back control, there should be a way to get a Facebook ID for that user. I'd send this ID alone to my OAuth2 endpoint with an extension grant understood by my server as "using an FB User ID".
Please note that I am still heavily researching on all this stuff, so that might not be a perfect answer... maybe not even a correct one! But I think that would make for a good starting point.
The idea of using an "extension grant" for the Facebook authentication might involve having to register it to do things properly? I'm not quite sure.
Anyway, I hope I was able to help you even a bit, and that at least it can start a discussion to find the best solution to this problem :)
Update
The Facebook login is not a solution as pointed in the comments: anybody could send an arbitrary user ID and log in as this user on the API.
What about doing it like this:
Show a login form with a "Facebook login" button
If this login method is chosen, act kinda like the Facebook SDK: open a web page from your authentication server, which will initiate the Facebook login.
Once the user has logged in, Facebook will use your redirect URL to confirm; make that URL point to another endpoint of your authentication server (possibly with an extra parameter indicating the call came from an app?)
When the authentication endpoint is hit, the authentication can securely identify the user, retain its FB User ID/FB Session and return an access token to your app using a custom URL scheme, just like the Facebook SDK would do
Looks better?