Understanding OAuth in Ruby on Rails
OAuth is the most common way to securely authenticate users via third-party services like Google, GitHub, or Facebook. This guide will walk you through its purpose, implementation, real-world use cases, and common questions.
🧾 Detailed Explanation (Easy to Understand)
Let’s break down how OAuth works in a Ruby on Rails application in a very simple way:
- User Clicks “Login with Google”:
Your app has a button that redirects the user to Google (or another provider) for authentication. - User Logs In on Google:
The user enters their Google credentials on the official Google login page—not on your site. This is secure because your app never sees the password. - Google Redirects Back with a Token:
After the user logs in successfully, Google sends your Rails app a special “authorization code” or “access token”. - Your App Uses the Token:
Your app uses this token to ask Google for details like the user’s name, email, and profile picture—only what the user allowed. - You Find or Create a User:
Your app checks: “Do I already have a user with this email?” If yes, it logs them in. If not, it creates a new user account. - Session Is Created:
The user is now logged into your app just like any other user—but you didn’t handle a password at all!
🔐 This whole process makes login faster, safer, and often more trusted since users know and trust providers like Google or GitHub.
📚 Terms & Key Concepts
This table explains all important terms you’ll encounter when working with OAuth in Ruby on Rails:
Term | Description |
---|---|
OAuth | An open protocol for secure authorization between applications without exposing user credentials. |
Access Token | A short-lived token issued after a user logs in; used to access the user’s data securely. |
Refresh Token | A long-lived token used to get a new access token without logging in again. |
Client ID | A unique identifier for your app provided by the OAuth provider (e.g., Google). |
Client Secret | A secret key that, along with the client ID, authenticates your app with the provider. |
Provider | The third-party service that authenticates users (e.g., Google, Facebook, GitHub). |
Callback URL | The route on your app where the provider sends the token after login success. |
Scope | A set of permissions requested from the user (e.g., email, profile). |
Authorization Code | A temporary code that is exchanged for an access token. |
Devise | A flexible Rails authentication library commonly used with OAuth strategies. |
OmniAuth | A library that enables multi-provider authentication for Rails apps. |
🔁 OAuth Flow & Usage Areas
Let’s understand the typical OAuth flow used in Ruby on Rails apps:
- User clicks “Login with Google” – Triggers the authentication request.
- User is redirected to Google – They log in on Google’s site.
- Google sends a token back to your Rails app – This happens via a callback URL.
- Rails exchanges the token for user data – Like email, name, or profile image.
- User is logged into your app – Without ever typing a password into your site!
Visual representation of the OAuth flow:
[User Clicks Login] ↓ [Redirect to Provider (Google)] ↓ [User Grants Access] ↓ [Provider Sends Token to Your App] ↓ [App Fetches User Info] ↓ [User Signed In]
📍 Where is OAuth Commonly Used?
- ✅ Web Applications – Login with Google, GitHub, or Facebook.
- ✅ API Services – Apps need permission to access data on behalf of users (e.g., Calendar, Gmail).
- ✅ Single Sign-On (SSO) – Corporate tools using one login across multiple internal systems.
- ✅ Mobile Apps – OAuth providers like Google or Apple handle mobile login flows.
- ✅ Shopify, Slack, Discord Apps – Where apps integrate with user accounts via OAuth access tokens.
🎯 Goal of OAuth: Give users a secure way to log in or authorize your app without ever typing a password into your system.
🔧 Gems and Libraries Used for OAuth in Rails
To implement OAuth in a Ruby on Rails app, you typically use a combination of the following gems and tools:
Gem / Library | Purpose |
---|---|
devise | Handles authentication in Rails (sign up, login, password, session management). |
omniauth | A flexible authentication library for integrating third-party login (OAuth, SAML, etc.). |
omniauth-rails_csrf_protection | Protects your app from CSRF attacks during OmniAuth callbacks. |
omniauth-google-oauth2 | Provides OAuth strategy for authenticating with Google in Rails. |
dotenv-rails | Helps manage environment variables like GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET . |
figaro (alternative to dotenv) | Another gem to manage secure app configuration (ENV secrets). |
📦 These gems work together to offer secure, plug-and-play OAuth authentication with support for multiple providers.
🚀 Best Implementation: Google OAuth in Ruby on Rails (Step-by-Step)
This is the recommended and secure way to implement Google OAuth in your Rails app using Devise
and OmniAuth
.
📋 Step 1: Install Required Gems
# Gemfile
gem 'devise'
gem 'omniauth-google-oauth2'
gem 'omniauth-rails_csrf_protection' # Prevent CSRF attacks during OAuth
gem 'dotenv-rails', groups: [:development, :test] # Manage ENV variables
$ bundle install
🛠 Step 2: Set Up Devise
$ rails generate devise:install
$ rails generate devise User
$ rails db:migrate
🔑 Step 3: Get Google Credentials
Go to Google Developer Console:
- Create a new project
- Enable “Google+ API” or “People API”
- Go to “OAuth Consent Screen” → Fill app details
- Go to “Credentials” → Create OAuth Client ID
- Set Authorized redirect URI to:
http://localhost:3000/users/auth/google_oauth2/callback
- Copy your Client ID and Client Secret
🔒 Step 4: Store Credentials Securely
# .env
GOOGLE_CLIENT_ID=your_google_client_id_here
GOOGLE_CLIENT_SECRET=your_google_client_secret_here
# config/application.rb
Dotenv::Railtie.load
⚙️ Step 5: Configure Devise with OmniAuth
# config/initializers/devise.rb
config.omniauth :google_oauth2,
ENV['GOOGLE_CLIENT_ID'],
ENV['GOOGLE_CLIENT_SECRET'],
{ scope: 'userinfo.email,userinfo.profile' }
👤 Step 6: Update Your User Model
# app/models/user.rb
devise :omniauthable, omniauth_providers: [:google_oauth2]
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.email = auth.info.email
user.name = auth.info.name
user.password = Devise.friendly_token[0, 20]
end
end
🧭 Step 7: Create Callback Controller
# app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def google_oauth2
@user = User.from_omniauth(request.env['omniauth.auth'])
if @user.persisted?
sign_in_and_redirect @user, event: :authentication
else
redirect_to new_user_registration_url, alert: "Something went wrong."
end
end
end
🛣 Step 8: Add Routes
# config/routes.rb
devise_for :users, controllers: {
omniauth_callbacks: 'users/omniauth_callbacks'
}
🧪 Step 9: Add Login Link to View
<%= link_to "Sign in with Google", user_google_oauth2_omniauth_authorize_path %>
✅ Step 10: Test It
- Run your Rails server:
rails s
- Go to:
http://localhost:3000
- Click “Sign in with Google”
- Authorize via Google → Get redirected back → User is created/logged in!
🧠 Pro Tips
- Always use HTTPS in production
- Whitelist correct redirect URIs in Google Console
- Add fields like
:provider
and:uid
to your users table if missing - Style your login button to match Google branding
- To allow multiple providers (e.g., GitHub), just repeat this with a new strategy
🎤 OAuth Interview Questions & Answers
1. What is OAuth and why is it used?
Answer: OAuth is an open protocol that allows secure authorization without exposing user credentials. It’s used to let users log in using external providers like Google, GitHub, or Facebook while giving limited access to resources.
2. What is the difference between authentication and authorization in OAuth?
Answer: Authentication is about verifying who the user is; authorization is about what they are allowed to access. OAuth primarily deals with authorization but is commonly used for authentication (e.g., logging in via Google).
3. What’s the role of an access token?
Answer: An access token is issued after a successful OAuth flow and is used to access the user’s data or APIs securely. It acts as a temporary key with defined permissions (scopes).
4. How do you implement Google OAuth in a Rails app?
Answer: Using devise
and omniauth-google-oauth2
gems. You configure the strategy in devise.rb
, set up routes and callbacks, and fetch user data from the OAuth response to log in or create a user.
5. What are scopes in OAuth?
Answer: Scopes define what level of access your app is requesting. For example, userinfo.email
or calendar.readonly
when working with Google APIs.
6. What is a callback URL and why is it important?
Answer: It’s the endpoint in your app that the provider redirects back to after the user authorizes access. It must match the one registered in the provider console for security reasons.
7. What happens if the user denies access?
Answer: The provider redirects back to your callback URL with an error parameter. Your app should handle this gracefully, usually by showing a message like “Authorization failed.”
8. How do you handle token expiration in OAuth?
Answer: Use the refresh token (if granted) to obtain a new access token when the old one expires. This is done via a server-side background job or on-demand refresh request.
9. How do you prevent CSRF attacks during OAuth flow?
Answer: Use the omniauth-rails_csrf_protection
gem, which adds a CSRF token to the OAuth request and verifies it upon return to your callback endpoint.
10. What is the difference between OAuth1 and OAuth2?
Answer: OAuth1 uses complex cryptographic signatures and was harder to implement. OAuth2 is simpler, uses bearer tokens, supports more grant types, and is the current standard.
🔄 OAuth vs SSO (Single Sign-On)
Many developers confuse OAuth and SSO because they both deal with user identity, but they serve different purposes. Here’s a clear breakdown:
🧠 Key Difference:
OAuth is a protocol for authorization (delegating access), while SSO is a feature that allows one set of credentials to access multiple systems.
📊 Comparison Table:
Feature | OAuth | SSO |
---|---|---|
Purpose | Delegates access to user data/resources | Allows access to multiple systems with one login |
Used For | Authorizing APIs, social login | Unified login across apps (Gmail, Drive, YouTube) |
Requires Token? | Yes, access and refresh tokens | Not necessarily — uses session or identity provider |
Involves Authorization? | ✅ Yes | ❌ Not always |
Involves Authentication? | Indirectly (via provider) | ✅ Yes, direct login |
Example | “Allow this app to access your Google Calendar?” | Login once to access Gmail, YouTube, Drive |
🧪 Real-World Example
- OAuth: A third-party fitness app asks permission to read your steps from your Google Fit account.
- SSO: Logging into Slack and Trello with your Google account using one shared identity (Google ID).
✅ Summary: OAuth is a protocol to give limited access, SSO is a convenience feature to reduce multiple logins.
🔁 Alternatives to OAuth
OAuth is widely adopted, but there are several other protocols and strategies available for user authentication and authorization. Depending on the use case, one of the following alternatives might be better suited:
Alternative | Description | When to Use |
---|---|---|
🔐 SAML (Security Assertion Markup Language) | XML-based protocol used for enterprise Single Sign-On (SSO) | Enterprise apps, corporate login via Microsoft/Azure/Okta |
🧾 OpenID Connect | Built on top of OAuth2, specifically for user identity (authentication) | Modern web & mobile apps needing both login and user profile |
🔑 API Keys | A simple string token used for accessing APIs (no user context) | Server-to-server communication, internal APIs |
📨 JWT (JSON Web Tokens) | Token-based auth — often used in custom implementations | Custom login flows, SPAs (e.g., Rails API + React/Vue) |
🗝 Devise + Password | Traditional email/password auth via Devise (no external provider) | Internal apps, where users sign up directly on your platform |
🛠 HTTP Basic Auth | Sends credentials with every request using the Authorization header | Testing, simple internal APIs, not recommended for production |
✅ Summary
- Use
OAuth
for public apps needing access to user data on external platforms. - Use
OpenID Connect
for identity/authentication flows (e.g., login). - Use
SAML
for enterprise SSO and federated identity systems. - Use
JWT
when building your own stateless API authentication.
🛠️ Can You Create Your Own OAuth System for Others to Use?
Yes, you can build your own OAuth 2.0 provider in Ruby on Rails so that other applications (like third-party web apps, mobile apps, or internal tools) can authenticate and access user data through your platform — just like Google, Facebook, or GitHub do.
📦 When Should You Create Your Own OAuth Provider?
- ✅ You run a platform or service that other apps need to integrate with
- ✅ You want to allow third-party developers to build apps using your APIs
- ✅ You need centralized authentication across multiple internal systems (SSO)
- ✅ You want fine-grained control over user authorization scopes and data access
⚙️ How to Build Your Own OAuth Provider (Overview)
You’ll need to implement the OAuth 2.0 flow in your Rails app. Here’s a high-level breakdown:
- Create a system to manage client apps: Developers can register their app, get a
client_id
andclient_secret
. - Build an authorization endpoint: Clients redirect users here to log in and authorize permissions.
- Implement token exchange: After the user authorizes, issue an access token to the client app.
- Secure your APIs: Require access tokens to fetch data via APIs.
- Support scopes and expiration: Define permissions (e.g., read-only, write access) and set token TTLs.
🧰 Libraries That Help You Build an OAuth Provider
Gem | Purpose |
---|---|
doorkeeper | The most popular gem to turn your Rails app into an OAuth 2 provider. Supports access tokens, refresh tokens, scopes, expiration, etc. |
devise | Used to manage user sessions and handle user login/logout. Doorkeeper can be integrated with Devise. |
🔐 Security Considerations
- Always use HTTPS
- Validate
redirect_uri
strictly - Store tokens securely
- Implement proper scope management
- Log and monitor token usage
📈 Real-World Example
Spotify, GitHub, and Shopify all offer their own OAuth providers. You log in once, authorize access, and third-party tools (like analytics dashboards or integrations) can act on your behalf using access tokens.
✅ So yes — with the right architecture and security in place, you can absolutely offer your platform as an OAuth provider.
🧠 Technical Questions & Real-World Case Studies on OAuth
💡 Technical Questions (Beginner to Advanced)
- What is OAuth and how does it differ from authentication?
OAuth is for authorization — giving apps access to limited user data. Authentication verifies user identity. OAuth doesn’t prove who the user is, just what they’re allowed to do. - Explain the OAuth 2.0 flow in detail.
The client redirects the user to the authorization server → user logs in and grants permission → server redirects back with a code → client exchanges the code for a token → uses token to access APIs. - What are the different OAuth 2.0 grant types?
– Authorization Code (used by web apps)
– Implicit (legacy for SPAs, not recommended)
– Client Credentials (server-to-server)
– Resource Owner Password (deprecated in many cases) - When would you use the client credentials flow?
Use it when no user is involved — e.g., a backend service authenticating with another backend service. - What is a refresh token?
It’s a long-lived token used to obtain a new access token without re-authenticating the user. Useful for keeping sessions alive. - Authorization Server vs Resource Server?
Authorization Server: issues tokens
Resource Server: serves protected data and validates tokens - Access Token vs ID Token?
Access Token = for API access. ID Token = for identity (used in OpenID Connect). - How do scopes work in OAuth?
Scopes define what parts of the user’s data the app can access. Example: `email`, `profile`, `calendar.readonly` - What is PKCE and why is it important?
PKCE (Proof Key for Code Exchange) secures OAuth for public clients like mobile apps that can’t store secrets. - How do you revoke OAuth tokens?
Use the provider’s revoke endpoint or remove the token from your DB/session cache. Google, GitHub, etc. support revocation. - How to secure tokens in Single Page Apps?
Store tokens in memory or HTTP-only cookies. Avoid localStorage due to XSS risks. Use backend proxies when possible. - What happens if access tokens are leaked?
Anyone can impersonate the user. Use short-lived tokens, rotate refresh tokens, monitor usage, and revoke tokens if needed. - What is a bearer token?
A token sent via Authorization headers (e.g., `Authorization: Bearer <token>`) that grants access to a resource. - OAuth 1.0 vs OAuth 2.0?
OAuth 1.0 required cryptographic signing, was complex. OAuth 2.0 is simpler, supports more flows, but requires extra security layers like PKCE. - How to implement OAuth for third-party access to your API?
Use thedoorkeeper
gem to turn your Rails app into an OAuth provider and manage tokens, clients, and scopes. - How to protect against CSRF in OAuth?
Use state parameters, theomniauth-rails_csrf_protection
gem, and avoid redirecting to untrusted domains. - How to handle token refresh in React frontend?
Store refresh token securely (preferably in HTTP-only cookie). Use silent refresh or background jobs to obtain new access tokens. - How to validate an access token on the API server?
Use introspection endpoints or decode JWT tokens and verify the signature, expiry, and audience claims. - How does JWT integrate with OAuth?
JWTs are often used as access tokens. They carry claims and are self-verifiable by the resource server without needing to call the auth server. - How to support multiple providers in one app?
Use OmniAuth to handle different providers (Google, GitHub, Facebook). Store `provider` and `uid` in your User model and match users accordingly.
📈 Real-World Example: Shopify OAuth
Shopify apps use OAuth2 for merchant authentication. Once a store owner installs an app, they’re redirected to Shopify’s OAuth flow. The app receives an access token to interact with the store’s API — without needing passwords.
✅ Best Practices
- 🔒 Always use HTTPS
- 🔐 Store tokens encrypted
- 🕓 Handle token refresh gracefully
- 📡 Never expose tokens to the frontend
- 💡 Validate the token on every call
Learn more about Rails setup