Skip to content

Services, Wiki-Artikel, Blog-Beiträge und Glossar-Einträge durchsuchen

↑↓NavigierenEnterÖffnenESCSchließen
Identity & Access Management Glossary

OAuth 2.0 / OpenID Connect

OAuth 2.0 is an authorization framework that allows applications to access resources on a user’s behalf with limited permissions. OpenID Connect (OIDC) builds on OAuth 2.0 and adds authentication—the foundation for modern single sign-on and social login.

OAuth 2.0 enables a fundamental improvement in security: Instead of giving third-party apps your password (which is actually what used to happen!), the user grants the app only the specific permissions it needs—for a limited time, and revocable at any time. OpenID Connect extends OAuth with standardized identity information.

OAuth 2.0 explained in one sentence

Analogy: In a hotel, you don’t give the valet your house key, but rather a valet key that can only start the car. With OAuth, you don’t give the app your password, but rather a token that only allows certain actions.

Without OAuth (historically): > "Please enter your Google password so we can import your contacts" - The app had full access to everything; revocation was only possible by changing the password.

With OAuth 2.0: > "Allow XY app access to: Your contact list (read-only)" - Token with limited scope; Revocation possible at any time in Google settings, without changing the password.

The OAuth 2.0 Components

The 4 Roles

Resource Owner (User):

  • Owns the resources (emails, contacts, etc.)
  • Grants access permission

Client (Application):

  • App that wants to access resources
  • Registers with the Authorization Server (receives Client ID + Secret)

Authorization Server (IdP):

  • Issues Access Tokens upon consent
  • Examples: Google, Microsoft Entra ID, Auth0, Keycloak

Resource Server (API):

  • Holds the resources (Gmail API, Calendar API)
  • Accepts Access Tokens and returns data

Key Concepts

TermMeaning
Access TokenShort-lived (15 min–1 hr), for API access
Refresh TokenLong-lived (7–30 days), retrieves new access tokens
ScopeWhich permissions? (read:contacts, write:calendar)
StateCSRF protection during authorization requests
PKCEProof Key for Code Exchange (for public clients)

OAuth 2.0 Flows

When: Web apps, mobile apps, single-page apps Security: Highest (code is exchanged for a token)

Process:
a) App generates code_verifier (random) + code_challenge (SHA256 of the former)
b) App sends user to IdP:
   GET /authorize?
     client_id=abc
     &response;_type=code
     &scope;=openid email
     &redirect;_uri=https://app.firma.de/callback
     &state;=randomValue
     &amp;code;_challenge=<hash>
     &amp;code;_challenge_method=S256

c) User logs in to the IdP
d) IdP redirects to callback with authorization code:
   GET /callback?code=auth_code_123&amp;state;=randomValue

e) App exchanges code for token:
   POST /token
     grant_type=authorization_code
     &amp;code;=auth_code_123
     &amp;redirect;_uri=https://app.firma.de/callback
     &amp;client;_id=abc
     &amp;code;_verifier=<original_verifier>  ← PKCE!

f) IdP returns:
   { &quot;access_token&quot;: &quot;...&quot;, &quot;refresh_token&quot;: &quot;...&quot;, &quot;id_token&quot;: &quot;...&quot; }

2. Client Credentials Flow

When: Server-to-server (no user involved) Example: Microservice calls another API

POST /token
  grant_type=client_credentials
  &amp;client;_id=service-a
  &amp;client;_secret=secret
  &amp;scope;=api:read

Deprecated Flows - Do Not Use

  • Implicit Flow (deprecated): Token in URL → History, logs, Referer header; replaced by Authorization Code + PKCE
  • Password Grant Flow (deprecated): App receives password directly → OAuth security compromised; only for legacy migration

OpenID Connect (OIDC)

OIDC = OAuth 2.0 + Identity Layer

What OIDC adds:

  • ID Token (JWT): Who is the user?
  • /userinfo Endpoint: Retrieve user information
  • Standard Scopes: openid, profile, email, phone, address
  • Discovery endpoint: /.well-known/openid-configuration
// ID token content (JWT payload):
{
  &quot;iss&quot;: &quot;https://accounts.google.com&quot;,     // Issuer
  &quot;sub&quot;: &quot;10769150350006150715113082367&quot;,    // Subject (User ID)
  &quot;aud&quot;: &quot;client_id_123&quot;,                   // Audience (your app)
  &quot;exp&quot;: 1311281970,                        // Expiry
  &quot;iat&quot;: 1311280970,                        // Issued At
  &quot;nonce&quot;: &quot;0394852-3190485-2490358&quot;,        // CSRF protection
  &quot;email&quot;: &quot;user@example.com&quot;,
  &quot;email_verified&quot;: true,
  &quot;name&quot;: &quot;Max Muster&quot;
}

Important validations of the ID token:

  1. iss == known issuer (not "Evil IdP"!)
  2. aud == your client ID (no token substitution attack!)
  3. exp > now (token not expired)
  4. nonce == sent nonce (CSRF protection)
  5. Signature valid with IdP public key
  6. Algorithm: RS256 or ES256 (not none or HS256!)

OAuth Security Vulnerabilities

1. Redirect URI Validation (most common vulnerability)

WRONG: Redirect URI whitelist: &quot;https://app.firma.de/*&quot;
Attack: redirect_uri=https://app.firma.de/callback?next=https://attacker.com
→ OAuth code is forwarded to attacker.com!

CORRECT: Exact URI (no wildcards!):
Whitelist: [&quot;https://app.firma.de/callback&quot;]

2. State parameter missing (CSRF)

Attack: Attacker tricks victim into starting OAuth flow with attacker's code → Victim logs into app using attacker's account. Protection: Set and validate state parameter!

3. Open redirect via Redirect URI

If app redirects to user-specified URL after OAuth:

Attack: ?redirect=/after-login?url=https://phishing.com
Protection: Only allow permitted relative URLs as redirects

4. Authorization Code Interception (without PKCE)

Code visible in URL → Referer header, proxy logs. Protection: Enforce PKCE (code_challenge)

5. Token Leakage in Logs

Access tokens in URL parameters → Server logs contain tokens. Protection: Tokens ONLY in Authorization headers, never in URLs

Attacker registers app with Google/Microsoft using a credible name ("IT Support Tool") and broad scope (offline_access, Mail.ReadWrite). User grants consent → Attacker has full access to mailbox. Protection: Conditional Access Policy → Admin approval for new apps

Implementation: Node.js with Passport.js

// Express + Passport.js + OIDC

import passport from &#x27;passport&#x27;;
import { Strategy as OIDCStrategy } from &#x27;passport-openidconnect&#x27;;

passport.use(new OIDCStrategy({
  issuer: &#x27;https://accounts.google.com&#x27;,
  authorizationURL: &#x27;https://accounts.google.com/o/oauth2/v2/auth&#x27;,
  tokenURL: &#x27;https://oauth2.googleapis.com/token&#x27;,
  userInfoURL: &#x27;https://openidconnect.googleapis.com/v1/userinfo&#x27;,
  clientID: process.env.GOOGLE_CLIENT_ID,
  clientSecret: process.env.GOOGLE_CLIENT_SECRET,
  callbackURL: &#x27;https://app.firma.de/auth/callback&#x27;,
  scope: [&#x27;openid&#x27;, &#x27;email&#x27;, &#x27;profile&#x27;],

  // Security:
  pkce: true,       // Enable PKCE!
  state: true,      // State parameter for CSRF protection
}, async (issuer, profile, done) =&gt; {
  // Find or create user in database
  const user = await User.findOrCreate({ googleId: profile.id });
  return done(null, user);
}));

// Routes:
app.get(&#x27;/auth/google&#x27;, passport.authenticate(&#x27;openidconnect&#x27;));

app.get(&#x27;/auth/callback&#x27;,
  passport.authenticate(&#x27;openidconnect&#x27;, { failureRedirect: &#x27;/login&#x27; }),
  (req, res) =&gt; res.redirect(&#x27;/dashboard&#x27;)
);
```</original_verifier></hash>