This document discusses using Doorkeeper and OAuth 2.0 to protect APIs. It provides an overview of OAuth concepts like access tokens, scopes, applications, roles, and grant types. It then covers setting up Doorkeeper, including defining scopes, protecting controllers, handling user groups, password resets, and testing. Real-world uses of OAuth like email logins, first-party apps, third-party apps, native apps, and API documentation are also mentioned.
3. Definition
• “Who are you?”
• Establishing identity
• 401 Unauthorized
• “Can you do this?”
• Verifying access
• 403 Forbidden
Authentication Authorization
4. • Alternative to session cookies
• Embraces HTTP statelessness
• You don’t to have to worry about CSRF
• Ajax/SPA friendly
• Authorization: Bearer <token>
Token Based Authentication
8. Access Tokens Scopes ApplicationsRoles
Concepts
Resource Owner Client Resource Server Authorization Server
“End-user” when
referring to a person
Capable of granting
access to protected
resource
The application
making
requests/accesses
the protected
resource on behalf
of the user
The server hosting
the protected
resource
The server issuing
access tokens to the
Client
Often same server
as the Resource
Server
9. Access Tokens
• Access tokens are often randomly generated strings,
opaque to the client
• Associated with a set of scopes
• Has a limited lifetime
• Can be made self contained with JWT
Scopes ApplicationsRoles
Concepts
10. Access Tokens Scopes ApplicationsRoles
Concepts
• Scopes define capabilities in your system
• Often divided in *_read and *_write
• Using scoped access token make it possible to create
levels of privileges
11. Access Tokens Scopes ApplicationsRoles
Concepts
• Represent a 3rd party
• Has client_id and client_secret
• Public or Confidential
• Must provide a Redirect URI
14. Grant Types
Authorization Code Most used
Implicit Not recommended
Resource Owner
Password
Use only for 1st party
apps
Client Credentials
Lets the Application acts
on behalf of it self
16. Endpoints
GET /authorize
Returns a human-friendly HTML page
with an “Authorize” and an “Decline”
button. Should somehow redirect user
POST /authorize
Used to obtain authorization grant via
user-agent redirect
POST /token
Used to exchange authorization grant
into access token
GET Client Redirect Endpoint
Where user-agent should redirect to after
/authorize
18. • Token are issued with a limited life time
• Issued alongside access tokens
• Refresh tokens can be exchanged for new access tokens
• client_id and client_secret needed to refresh
• Uses the refresh_token grant type
Refresh tokens
19. Grants for Native Apps
• Possible to redirect from browser to native app, e.g.
webshipr://authorized
• Client secret cannot be used
• The Proof Key for Code Exchange (“pixie”) is an extension
to Authorization Code grant type
26. Handling User groups
• Business decision: Password grant tokens inherits scopes
from user group
• Business decision: Grant type authorization code can
elevate scopes
28. • Confirmation email on create
• Custom logic for password reset token and confirmation
email
• Special scope write_reset_password for setting password
Password Resets
33. Real world uses
• Email/password logins
• 1st party applications
• 3rd party applications
• Native applications
• Mobile apps
• API explorer in docs
34. The OAuth 2.0 Authorization Framework
https://tools.ietf.org/html/rfc6749
https://oauth.net/
An Introduction to OAuth 2
https://www.digitalocean.com/community/tutorials/an-introduction-to-
oauth-2
OAuth 2.0 Threat Model and Security Considerations
https://tools.ietf.org/html/rfc6819
Doorkeeper Github repo
https://github.com/doorkeeper-gem/doorkeeper
References
Lad os først få et par begreber på plads.
Autentifikation eller Autorisation
Brug de engelske order for at holde et simpelt
To forskellige begreber. Begge forkortet “Auth”
Bemærk: HTTP Statuskoderne er ikke intuitive
Et andet vigtigt begreb er Token Based Authentication, det er hele pointen med den her talk.
Traditionelle websider bruger session cookies og CSRF tokens til at skabe Authentication mellem Clienten og Serveren. Session cookies bruger at abstrahere HTTP statelessness væk - men jeg synes at vi som udvikere burde omfavne alle HTTP’s egenskaber. Ved at abstrahere session cookies væk, glemmer man
Authentication er en så vigtig del af web udvikling at man skal have styr på hvordan det fungerer.
Bemærk: Og her betyder Auth Authentication og her skal man bruge headeren Authorization
API-first betyder at man ser sin API som sin primære kilde til sin data og logik.
Alt andet er applikationer der udnytter API.
Web app’en kan være:
1) en single page app, der ikke bliver leveret fra samme server/service som API’en (som hos Webshipper)
2) Eller det kan være genereret HTML fra et klassisk Ruby on Rails projekt.
Bemærk: Browseren kender ikke forskel på de to! (Bortset fra CORS og Ajax vs HTML forms)
Ved en traditionel RoR projekt bruges session cookies til Authentication.
OAuth2.0 er en protokol til at uddelegere tillid.
Den bruger til at lade 3. parter tilgå en service (som regel en API) på vegne af en bruger. Single Click Signon and Apps til f.eks. Github er gode eksempler.
De grundlæggende begreber
OAuth2 definerer fire roller I protokollen: Resource Owner, Client, Resource Server, Auth server
Access Tokens giver adgang til en beskyttet resource i et forudbestemt stykke tid. Often tilfældige tekst strenge.
Scopes begrænser adgang til dine resource.
Man lavet oftes en “read” og én “write” per resource type.
Kan bruges til at lave brugergrupper med forskellige privilegier.
Et godt supplement til gems som CanCanCan der kan give/begrænse adgang til enkelte records.
Applications (også kalder Clients) er helt centrale i OAuth2. De beskriver en (oftes) 3.part der ønsker at tilgå din API (Protected Resource) på vegne af en af dine brugere.
Udstyret med client_id og client_secret, tilfældige uid’er
Skal være enten Public (SPA, Native, Mobile App) eller Confidential (Server backend).
Skal beskrive én redirect URL
Andet info: navn, logo, beskrivelse
Kan have liste af hvilke scopes den kan tilgå
OAuth består grundlæggende af 3 trin: Grant, Token exchange, Authenticated Request
Et Grant giver I sig selv ikke adgang til Resource’n, men skal byttes til et Access Token.
Auth og resource server er samlet, da de oftes er samme fysiske server
De sidste to trin kan udføres så længe Access Token’en er gyldig
Selvfølgelig: Så er intet af der her sikkert hvis man ikke bruger HTTPS!
End-brugeren er kun involveret i trinnet “Authorization Grant”
Brugeren giver sin tilladelse i en Authorization Prompt, her er det altså Auth Server’en der spørge Own’eren om Clienten på tilgå den beskyttede resource med de listede scopes.
Eksempel: Fra Webshippers nye platform. 1st party app. 1st party apps kan godt spørge direkte efter usernavn/password, men dette sparer brugeren fra at taste.
Grant types er måder for resource ejeren at give en 3rd part adgang
De her hver deres brug scenarier
Auth Code: Mest brugte
Implicit: Best practice har ændret sig siden OAuth2 blev formuleret, anbefales ikke at bruge mere
Resource Owner: Brugeren giver sit password væk, så kun for klient du virkelig stoler på
Client Credentials: Client snakker med API’et uden at der er en bruge involveret
Klik: Stjerne, Auth code mest anvendelige.
Viser kun denne for at undgå information overload. Se OAuth2.0 standarden for detaljer om de andre.
Dette er samme diagram som før, bare en implementation
Bruger klikker på link, ledt hen på Authorization Prompt’en
Bruger klikker Giv adgang
HTTP redirect
+ 5 Server-til-Server kommunikation der bytter authorization code til access token
Efter: Dette klienten kan bruge token’en til at tilgå resource’n
For at få alt dette til at ske, skal kan oprette disse endpoints:
OAuth2 specificere 3 endpoints: Authorization, Token og Client redirect end point
POST /authorize er ikke krævet af protokollen, men benyttes næsten altid sådan
I virkeligheden set det sådan ud.
Først, et link til “server”, altså Authorization Serveren
Bagefter: Redirect til client, “code” bliver sendt med som query parameter ved redirect
“Authorization: Basic” er client id og client secret. Validerer clienten for ”confidential clients”
Access Tokens har en begrænset levetid for at begrænse skaden hvis den bliver kompromiteret. En access token kan være sårbar overfor en dårlig HTTPS opsætning, exposure i server loggen eller ligne.
Refresh tokens kan ombyttes til en access token. Det kan konfigureres om refresh tokens skal issues.
I modsætning til access tokens udløber refresh tokens ikke, men kan blacklistes efter brug.
Native apps bruger custom url schemas til i deres redirect urls, som f.eks. webshipr://
Native Apps er en form for Public Clients.
Client secrets kan ikke gemmes i kompilet kildekode, det kan decompiles.
Eksempel fra PKCE specifikation der viser hvordan et authorization code kan opsnappes på OS niveau.
Advanceret angreb.
Doorkeeper er en gem der implementerer OAuth2 i Ruby on Rails. Doorkeeper implementerer rollen som OAuth “Auth Server”
“Resource Server” rollen er din service.
Guiden ligger på Github siden og jeg vil ikke gennemgå den skridt for skridt. Det er bedst med “hands on”.
Installation er ret ligetil:
- kør rake task
- kør migrations
- opsæt routes
Når doorkeeper er installeret så…
I doorkeeper initializeren doorkeeper.rb.
Vi har en del scopes, ca. 2 for hver resource I vores API.
Se detaljer for andre configs i Doorkeepers dokumentation.
For at beskytte sine controller skal man bruge doorkeeper_authorize!
Kvæver at request har en gyldig token
Denne controller kræver både at der eksiterer en gyldig token OG at read_posts/write_posts scopes existerer.
Vi bruger doorkeeper til at lave email/password logins. Alle brugere tilhører én brugergruppe.
For at holdet det enkelt har vi besluttet at tokens genereret med “resource owner password grant” skal arve scopes fra brugergruppen.
Vi har også besluttet, for at undgå forvirring bland brugere, at brugere kan Authorize clienter selvom appen kræver scopes brugeren ikke har.
Denne logik set sådan ud.
Denne Controller overskriver den del af Doorkeeper der resolver hvilken Grant Type strategy der er tale om.
Et passende sted at overskrive scopes inden en Access Token bliver genereret.
Her bliver de request’ede scopes overskrevet med brugergruppens scopes.
(Devise er en populær gem til håndtering af bruger authentication, her under signup, password reset.)
Brugeren kan være i flere states: active, reset_requested, locked osv.
Vi har valgt selv at implementere flowet omkring password resets og bruger oprettelse (samme logik) - Men det kan godt være muligt at bruge Devise.
Vi bruger tokens til at tilgå vores API, derfor også til at resette password.
Har var levet et specielt scope write_reset_password der kun giver tilladelse til dette.
Vi genererer en token i maileren.
Med en levetid på 4 timer
Og så sender vi den til brugeren
Når brugeren så trykker på linket
Vi har oprettet en controller med én action der:
Tjekker tokenen
Tjekker om passwords matcher
Sletter tokenen, for at undgå genbrug.
Og så returnerer vi et success response
Når man bruger spec types “request” kører rspec hele stakken igennem - ikke så meget magi, bare opret applications/brugere/osv. og send requests som specifikation foreskriver
Typen “controller” mocker man typisk authentication ud med en “sign_in” helper
sign_in helperen opretter:
en UserGroup, med passende scopes (oftes alle mulige), kan tilpasses i en before block
User
og en Doorkeeper::AccessToken
mocker tokenen på controlleren.
Hvad kan man så bruge det her til?
Indtil videre bruger vi OAuth2 til dette