ict.ken.be

Delivering solid user friendly software solutions since the dawn of time.

Introduction to OAuth2, OpenID Connect and JSON Web Tokens (JWT)

Categories: Security

By Dominick Baier

Enterprise security 

  • Kerberos/LDAP (intranet)
  • SOAP WS*, XML SAML (internet)

OAuth2 (Authorization Server)

  • Request token for backend consumption
  • Forward token to backend (webapi)

OpenID Connect (Authentication Server)

  • Request token for client consumption
  • Parse and validate token

Security Tokens

  • Security tokens are (protected) data structures
  • Contains information about issuer and subject (claims)
  • signed (tamper proof & authenticity)
  • typically contain an expiration time
  • A client requests a token
  • An issuer issues a token
  • A resource consumes a token (has a trust relationship with the issuer)

SAML 1.1/2.0

  • XML based
  • many encryption & signature options
  • very expressive

Simple Web Token (SWT)

  • Form/URL encoded
  • symmetric signatures only

JSON Web Token (JWT)

  • JSON encoded
  • symmetric and asymmetric signatures (HMAC-SHA256-384, ECDSA, RSA)
  • symmetric and asymmetric encryption (RSA, AES/CGM)
  • http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html

Header: metadata, algorithms & keys used
Claims: Issuer (iss), Audience (aud), IssuedAt (iat), Expiration (exp), Subject (sub), ... application defined claims, Signature

Header.Claims.Signature
{ "typ":"JWT", "alg":"HS256" }
{ "iss":"https://myIssuer", "exp":"1340819380", "aud":"https://myResource", "sub":"alice", "client":"xyz", "scope":["read", "search"]}

http://nuget.org/packages/Microsoft.IdentityModel.Tokens.JWT
SEND: var tokenString = new JWTSecurityTokenHandler().WriteToken(new JWTSecurityToken(...))
RECEIVE: principal = new JWTSecurityTokenHandler().ValidateToken(token, validationParams);

The OAuth 2.0 Authorization Framework (October 2012 - RFC6749, RFC6750)

  • Resource Server, Client, Resource Owner = User, Authorization Server
  • Valet Parking Key Analogy
  • Main goal is to assume the client is not trusted

Authorization Code Flow

  • Resource Owner -> Web Application -> Resource Server
  • 0. Client registers at authorization server 
  • 1a. Owner to AS: GET /authorize?client_id=webapp&scope=resource
  • &redirect_uri=https://webapp/cb&response_type=code&state=123
  • http://zachholman.com/2011/01/oauth_will_murder_your_children/
  • 1b. Owner to client: GET /cb?code=xyz&state=123
  • 2a. WebApp to AS: POST /token Authorization: Basic (client_id:secret) 
  • grant_type=authorization_code&authorization_code=xyz &redirect_uri=https://webapp/cb
  • 2b. AS to WebApp: token response access_token and refresh_token
  • 3. WebApp to Resource Server: GET /Resource
  • 4. send refresh tokens

Implicit Flow

  • 1a. Owner to AS: GET /authorize?client_id=webapp&scope=resource &redirect_uri=https://webapp/cb&response_type=token&state=123
  • 1b. AS to Client: GET /cb#access_token=abc&expires_in=3600&state=123
  • 3. GET /resource

Windows RT - WebAuthenticationBroker.AuthenticateAsync

Resource Owner Credential Flow

  • For trusted applications and devices
  • 1a. Client to AS: POST /token grant_type=password &scope=resource&user_name=owner&password=password
  • 1b. Token response, you should store the token and refresh token, not the credentials
  • Resource owner credentials are exposed to client
  • User should not become accustomed to typing in credentials everywhere

Client Credential Flow

  • No human involved at all
  • POST /token grant_type=client_credentials&scope=resource

OAuth2 abused for authentication by getting userinfo

Client to AS: GET /authorize?client_id=nativeapp&redirect_uri=http://localhost/cb&scope=signin&response_type=token&state=123
AS to Client: GET /CB?access_token
Client to Resource server: GET /userinfo

The Problem
1. User logs into maliciousapp that steals token
2. Malicious developer uses stolen access token in legitimate app (impersonated)

So we now have to write custom code for each provider (https://OAuth.io)

OpenID Connect (on top of OAuth2)

ID Token, UserInfo endpoint, discovery & dynamic registration, session management
Identity Provider, Authorization Endpoint, Token Endpoint, UserInfo Endpoint

  • 1a. user agent to ae: GET /autorize ... scope=openid profile

profile claims: name, family_name, given_name, middle_name, nickname, preferred_username, profile, picture, website, gender, birthdate, zoneinfo, locale, updated_at
email claims: email, email_verified
address: address
phone: phone_number, phone_number_verified
offline_access: requests refresh token

  • 1b. user agent to IP
  • 2b. token endpoint will return id_token on top of access_token

Client must validate the ID token (especially the audience must be himself)

  • 3a. UserInfo Request

Goal is to allow a client use an arbitrary OpenId Connect provider without code modifications

Eran Hammer (OAuth2 issues)

Protocol vs Framework (over 69 choices), so you can not implement the specification cause you need to build your own protocol.

  • RCF 6749 The OAuth2 Authorization Framework 
  • RFC 6750 OAuth2 Bearer Token Usage
  • RFc 6819 Threat Model and Security Considerations

Bearer Token
A security token with the property that any party in possession of the token (a "bearer") can use the token in any way that any other party in possession of it can. Using a bearer token does not require a bearer to prove possession of cryptographic key material (proof-of-possession). -> so everything depends on the safety of the transport layer, where plenty of developers ignore ssl certificate errors. (ServicePointManager)

Security Theater (Bruce Schneier)

  • Does the webview redirecting make sense?
  • Wouldn't it be better to let the application handle it all?

OAuth2 attack surface everywhere

Facebook Hacks

Specifications needs some refinement (basic profile, MAC tokens, ...)
Current implementations are lacking even by the big guys, let alone the myriad of DIY implementations

Very good & balanced view

Resources