OmniAuth Single Sign On with Devise, invalid_credentials - ruby-on-rails

I have 3 web apps - A, B and C. App A contains the user database. If accessing App B and App C, I would like the user to be redirected to App A to be authenticated, and then be returned back to whichever app they tried to access. At the same time, they should be logged in to all apps. Unless anyone has a better solution, I have gone with an OmniAuth/Devise combo solution as described in this blog post.
I have forked and updated to Rais 3.1.2 a sample App A and a sample app B/C.
App A - Provider - https://github.com/RobZolkos/sso-devise-omniauth-provider
App B/C - Client - https://github.com/RobZolkos/sso-devise-omniauth-client
These sample apps work, and I am get redirected to the Provider App to authenticate however it doesn't seem to authenticate. I have attached the log here. The provider seems to go through the motions, but then on line 26 of the log you can see that there seems to be an authentication issue.
Am I missing something simple to make these sample apps work?

I've found two issues:
Since 0.2.1 version omniauth has changed auth parameter name from access_token to oauth_token while fetching access (POST /oauth/token request).
Since 0.3.0 version omniauth has changed method of passing oauth_token in auth request (GET /auth/josh_id/user.json). Prior 0.3.0 token have been passed through request parameter oauth_token, but since 0.3.0 it become passed through HTTP_AUTHORIZATION header.
I don't know how to nicely get token from header (I think it can be fetched by devise), so I ugly hack client for sending oauth_token through GET parameter like this (in lib/josh_id.rb):
def raw_info
#raw_info ||= access_token.get("/auth/josh_id/user.json?oauth_token=#{access_token.token}").parsed
end
You can find fully workable code in our github repos:
https://github.com/openteam/sso-devise-omniauth-client
https://github.com/openteam/sso-devise-omniauth-provider

I have no experience with oauth in rails, but i'll explain the flow I used to create my own provider in Java. It should be easy to apply this in rails. If you use Devise with omniauth you need to find out, how they provide OAuth support and which version.
Basics
Consumer logs in to the app, and gets a consumer_key and consumer_secret. This is done with a regular form, usually on a developer account.
(optional)Provider approves the created account
All OAuth requests depend on a proper OAuth header in the request. A proper header means:
All oauth attributes and their values have been alphabetically sorted
All keys/tokens active for the particular Consumer request are provided.
The request is signed using all relevant secrets. Secrets are known to the Provider and Consumer but are not included in the header.
The Provider generates the same signature. If so, the request is valid. A nonce can be used to prevent replay attacks.
2-legged flow (consumer vs provider)
Consumer requests a resource, providing consumer_key.
Provider checks signature based on consumer_key and consumer_secret
Access to resource is granted
3-legged flow (person vs consumer vs provider)
Consumer request resource providing its consumer_key
Consumer gets a unsigned oauth_token and oauth_token_secret from Provider
User(person with user account on the provider) logs in at provider to authorize the oauth_token providing the oauth_request_token and consumer_key
Consumer has a authorized request_token
Consumer uses the request_token to request a access_token providing the oauth_request_token and consumer_key
Provider gives a access_token and access_token_secret for the specific resource
Consumer uses access_token to do something
Provider invalidates access_token after a certain duration
Consumer uses the request_token again to get a new access_token if expired
A decent resource for oauth is the official site.
For 3 legged examples you can have at the google oauth playground

Related

After getting token using Authorization Code Flow (OAuth 2.0), how can API knows that token sent from front end is valid?

Lets say I have created my own application. We have react front end and RESTful API as backend and we are using Google OAuth for Authorization of our users. Front end is making calls to the APIs. Front end uses Authorization Code Flow of OAuth. After getting access token from Google OAuth server, front end uses this token to make calls to my backend.
Now Malicious user will get my API's URL, other information required for REST API from Chrome Network tab and can call directly to APIs with access token.
Questions:
How will my REST API know from where the request is coming?
Also how it will validate the access token?
Is it possible once User got all information about my REST API, it can call directly with fake access token?
I have look into the diagram for Authorization Code Flow. Below is the link.
https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-app-types
But how will web api validate the token?
Please guide me if I am lacking some information.
Google's OAuth server will issue your front-end a JSON Web Token (JWT). This token is singed by Google private key. Your API needs to:
Obtain Google's public key and
Verify the signature of the JWT.
If that is valid, the token originated from Google. If not, it didn't come from Google or was tampered with.
After this, your API needs to do a few additional checks:
Check the expiration time and see that it's not in the past. This can be found in the exp claim.
Check that the token is not only from Google but for your API. This can be done by looking at the aud (audience) claim and seeing that it's for you.
Check when the token was issued, and ensure that it's not in the future. The issuance time is in the iat claim.
Check that you should start using it already, and there wasn't some sort of embargo on the usage period. This will be indicated in the not-before claim (nbf).
Check that the type of token is an access token (as opposed to an ID token).
(You can find a longer more detailed description in this howto.)
If you do these things, you can be sure that Google issued the token and that it was intended for your API. It does not indicate to your API that the caller was your front-end. The reason is that the token is an "bearer token", meaning the token is bound only to the one that bears or presents it. To ensure that only your app provides the token, you need it to prove possession of a private key. This is not possible when using Google as your token issuer (to my knowledge).
My question is basically how do my rest api validate integrity of the token. I found the link: https://developers.google.com/identity/sign-in/android/backend-auth

Protect the API by token/api key

A newbie question about API security:
When I applied API service from some API providers, usually I just login and generate an api key or token in their api management site. After that I can embed this api key or token in the request to access the API.
I was told that the this is OAuth 2. But, after reading a few articles about OAuth 2, it seems the OAuth-2 token issued from OAuth server will expire and a refresh-token is required to fetch a new token.
But the API keys I got from those API providers does not mention about the expiration, instead, I can manually revoke the API Key on their API management site.
So, if I have some APIs which I want to use the similar way (let the user manage their own api key on my site) to protect, how can I achieve that by using the OAuth 2 server?
I think what you explained above are 2 different ways to authorize a request:
A. Using API Keys
These API keys are usually a long string that you generate inside a dashboard
You as a developer would usually have 1 API key throughout your app, and you append this API key to requests to the API provider
B. Using OAuth 2.0
OAuth 2.0 uses a different kind of token to authorize requests, it usually involves a short-lived access token and long-lived refresh token.
These tokens are usually for Users, each user will have a different token that expires every X days.
To acquire a token, the user has to "log in" to your site or an Identity Provider's site (like Google Accounts) and enter their credentials every time the token expires.
Here's a picture to show the difference:
If you want to provide an API service for other developers:
Use OAuth 2.0 to log in the developers to their dashboard (this means your server routes that interact with the dashboard would be protected by the OAuth 2.0 tokens, requiring the developer to log in to update some settings)
Use API Keys to access your provided API routes. Developers have to log in and generate API keys from the dashboard. Then they can use this API key to fetch resources from your API.
Here's a more thorough explanation about OAuth 2.0, access tokens, and how to implement it on your site.

Open ID Token vs Oauth Token

I am new to OAuth and OpenId, and after reading multiple pages and information I still do not feel confident at all.
My goal would be to create an iOS Application that communicates with my BE. I need the iOS app to authenticate the user to access their resources.
Reading about OAuth, the solution seems to be straight forward. Just use the Authorization Code Flow with PKCE to make the App have an Access Token. This way I am authorizing my iOS app to access user's data. When the iOS app calls https://example.org/user with the access token, the resource service (my BE server) can get the access token and call the introspection API to know to which user the access token is bound to, and return the correct user data. Since authorization needs authentication to be made in the first place, having the access token would mean that the user is (or at least was) authenticated.
First thing that confuses me: According to the OAuth specs, OAuth is not an authentication protocol, but still the protocol authenticates the user using the user's credentials. Why is OAuth asking the user for credentials, instead of relying on another protocol/flow for user authentication? Such protocol would just acknowledge to OAuth that the authentication was successful.
This first issue made me start reading about Open ID Connect specification and the ID Token. This token would be received by the iOS app. What is the iOS App supposed to do with it? I can already get the user information calling the /user endpoint. How would this ID Token be an advantage?
tldr
Access token (OAuth 2.0) - authorize against OAuth protected
endpoints.
ID Token (OIDC) - authentiation by client application.
Authorization server authentication - It's there to detect
authenticity of end user involved in both protocols (pseudo
authentication from client application perspective)
OAuth is not an authentication protocol, but still the protocol contain a step to authenticate the user using the user's credentials
Correct, OAuth is not an authentication protocol. It is for authorization, which means identifying there are correct access grants to access a protected resource (protected resource ? ex:- An API, A photo stored in a backend).
So why you see end user login dialog ? Well that is the job of authorization server. It authenticate end user to be known by it and then issue the access token to client (client == in simple terms the application which end user uses). So yes there is an authenitcation happening, but this is not applicable to your client application or protected endpoint. One can define this as an pseudo authentication.
OpenID Connect - For authentication of client application
In the original RFC (RFC-6749), OAuth 2.0 was defined as a framework. OpenID Connect was an extension that built on this framework. What it provide ? Well as you found out, it introduce the ID Token. And ID token is issued by authorization server to be consumed by your client application. It contains end user identity information in JWT format. By validating integrity of this token, your client application can authenticate the end user. And access token ? That's there to used against protected endpoint. It doesn't say anything about end user to client.

Using access_tokens and id_tokens together Auth0

While starting to integrate auth0, I came across this article
So its clear that to secure apis, all we need is the access_token and that is sent with each http request in the request Authorization header(Bearer scheme).
But then auth0(and possibly other providers) also send an Id_token that contains information about the user. My confusion is that how do I use this id_token to pass user information to my api. ( I have a spa running front end that authenticates to auth0 and gets these 2 tokens).
I can ofc call the userInfo end point in my api to get user info. But then wouldn't this defeat the purpose of the Id tokens?
The ID Token is consumed by the application and the claims included,
are typically used for UI display. It was added to the OIDC
specification as an optimization so the application can know the
identity of the user, without having to make an additional network
requests.
So my question is how do I access user profile in my api using id tokens?
"My confusion is that how do I use this id_token to pass user information to my api"
for that confusion, you just pass your JWT token. while generating JWT token, you need to add user information in payload part in JWT token. When your api get the JWT token, just check your JWT token is correct or not by the use of secret key and if correct, you can get data. How to get is just go from that JWT Authentication for Asp.Net Web Api
ID token is sent from the authorization server as a part of OIDC protocol. The purpose of this is to authenticate the user to your client application (SPA in this case). i.e. to let your API or the application know which particular user authorized the client to access a certain resource on its behalf.
Best way to use the ID token is by decoding and verifying it using a library. This will allow you to verify the signature of the token and any other claim that is included in the token (you can add custom claims to the tokens). Validation of those claims can be used to determine identity of the user and match with the user profile in your API. You will have to check the documentation related to your IdP(auth0) to figure out how to add new claims that are used by the user profile in your API.

Reusing OAuth token and secret when Consumer key is changed in Twitter application (Rails)

I am working in a Rails application in which i use OmniAuth to authenticate user with Twitter.
Once user is authenticated properly, i then get the OAuth Token and OAuth Secret from Twitter.
I can then use this token and secret pairs to make api calls from my Rails application.
Consumer key from my twitter application is used to make api calls along with users token and secret.
Now, when my consumer key (of my twitter app) is changed. All the previously obtained OAuth token and secret are not working (i cannot use it to make api call).
How should i handle this situation when the consumer key is changed?
is there any way to refresh the Oauth token and secret with new consumer key without prompting user again to authenticate with twitter?
If you changed the consumer keys it means you are using different twitter application, how old application token supports new application? its not possible to merge two twitter application tokens.
Once you changed the consumer key, user again needs to authenticate the new twitter application.

Resources