Using an omniauth login strategy a non-logged in user is redirected to an identity provider. The identity provider, will ensure a user is logged in then redirect the user to a callback url allowing the user to login to the third party site, using the identity provider's authentication.. This workflow is explained by Facebook in their chart here:
https://developers.facebook.com/docs/user_registration/flows/
How is it assured that a malicious user does not spoof this callback so that he can gain access to the authenticating user's third party account?
Like Facebook, Google implements the OAuth2.0 protocol for confirming identity. I'll take you through how the OAuth2.0 process is secure, how OmniAuth manages it and show you how to take a look under the hood to see it in action.
The identity provider, will ensure a user is logged and then redirect the user to a callback url allowing the user to login to the third party site, using the identity provider's authentication.
Let me expand: The identity provider redirects the user to your application's callback URL that you supplied when you registered your application with that particular identity provider (ie Facebook, Google, etc). Since the user has been redirected, they send a request to your application containing an Authorization Code (supplied by your identity provider upon successful login).
How is it assured that a malicious user does not spoof this callback so that he can gain access to the authenticating user's third party account?
Here's where the magic happens. Our application takes this Authorization Code from the user, combines it with our Secret Code that we received upon registering our application and exchanges these with the identity provider for an almighty Access Code. Specifically, here are the steps taken to ensure this callback hasn't been spoofed:
Thus, it would be very difficult to intercept/decrypt a code and if you tried to spoof the redirect with a fake Authorization Code your login request would be rejected when your server tries to validate this code with your identification provider.
OmniAuth manages most of this process behind the scenes. However, the following code should allow you to see it in action:
# Add the following gem to your Gemfile
gem 'httplog', group: :development
We'll make use of the httplog gem. This will essentially dump request logs into our log/development.log file. We need to initialize:
# Create a new file: config/initializers/httplog.rb
HttpLog.options[:logger] = Rails.logger if Rails.env.development?
Now launch a new Rails server for you application in the terminal:
bundle install
rails s
In a new tab, tail your development logs:
tail -f log/development.log
Go ahead and open a browser and login to your application with your chosen identity provider. Open the terminal window tailing your development logs and after the callback request from the user (Started GET "/auth/google_oauth2/callback?state=1
) you should see something like:
[httplog] Connecting: accounts.google.com:443
[httplog] Sending: POST http://accounts.google.com:443/o/oauth2/token
[httplog] Data: client_id=123412341234-1234h1234h1234h1234h.apps.googleusercontent.com&client_secret=12341234123412341234&code=123412341234123412341234&grant_type=authorization_code&redirect_uri=https%3A%2F%2Fyourapp.domain.com%2Fauth%2Fgoogle_oauth2%2Fcallback
....
[httplog] Response:
{
"access_token" : "123412341234123412341234",
"token_type" : "Bearer",
"expires_in" : 3599,
...
}
This is your server verifying the Authorization Code and verifying the Access Token. Next, OmniAuth uses this token to get some user information. Further down you should also see:
[httplog] Connecting: www.googleapis.com:443
[httplog] Sending: GET http://www.googleapis.com:443/plus/v1/people/me/openIdConnect
[httplog] Status: 200
[httplog] Response:
{
"kind": "plus#personOpenIdConnect",
"gender": "male",
"sub": "1234123412341234",
"name": "Matt",
"given_name": "Matt",
...
}
This represents OmniAuth fetching the information you requested using the Access Token.
A long explanation, but I hope it helps. Be sure to disable or remove the httplog gem before pushing to production!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With