Authentication mechanism for your API
Przemek Lewandowski
@haxoza
About me
Overview
- Introduction
- Credentials vs API Keys
- Tokens vs Cookies
- Selected auth methods
- Summary
Design of API
- Authentication
- Resources
- Methods on resources
- Authroization
Identify client of API
- Internal application or developers
- Data belongs to the same organisation
- External application or developers
- Sharing data on behalf of your users
- User should decide what to share
Take into account
- Methods and standards
- System requirements
- System architecture
- Security issues
Credentials
vs
API Keys
Credentials
- Username/email and password
- Set by the user
- Only one valid password for the user
- Should be encrypted on the server
- Should not be send over the network
- Allows access to all user's resources
API Keys
- Depends on auth method
- identifier and secret token
- just a token
- or else
- Set by the system
- One or many valid api keys per user
- Identify client
- Not encrypted on the server
- Can expire
- Can be assigned to only some resources
Common use case
Tokens vs Cookies
Tokens vs Cookies
- Cookies are usually session based
- Tokens are stateless
- Tokens are mobile ready
- Some say that sessions are not efficient
- Cookies and CORS don't play well
Tokens vs Cookies
Selected auth methods
- Basic Auth
- Token Auth
- Digest Auth
- JSON Web Token Auth
- OAuth 2.0 / OpenID
Further assumptions
- API via HTTP
- Auth data mostly via HTTP headers
- Response header: WWW-Authenticate
- Request header: Authorization
- Some details are simplified
Basic Auth
2. Response: HTTP 401 Unauthorized
WWW-Authenticate: Basic realm="Hello there!"
1. Request: GET /invoices/
3. Request: GET /invoices/
Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l
4. Response: HTTP 200 OK
header_value = base64.encode("username:password")
Basic Auth
- Very simple
- Sends password with each request
- API should be available only over HTTPS
- Client app should forget the password
Token Auth
2. Response: HTTP 401 Unauthorized
WWW-Authenticate: Token
1. Request: GET /invoices/
5. Request: GET /invoices/
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
6. Response: HTTP 200 OK
4. Response: 200 OK
{"token" : "9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b"}
3. Request: POST /obtain-auth-token/
{"username": "john", "password": "secretpass"}
Token Auth
- Can support multiple client apps
- Allows for token invalidation
- Minimise password usage on the wire
- Tokens usually stored on the server
- API should be available only over HTTPS
Digest Auth (simplified)
2. Response: HTTP 401 Unauthorized
WWW-Authenticate: Digest nonce="123456"
1. Request: GET /invoices/
4. Response: HTTP 200 OK
3. Request: GET /invoices/
Authorization: Digest username="john" realm="xyz"
token=MD5(nonce, username, realm, URI, password))
Digest Auth
- Doesn't send plain password over wire
- Needs plain text password on the server
- Vulnerable to brute force attack
- Vulnerable to MITM attack
- Because of above should be behind HTTPS
Digest Auth + Token Auth
- Encrypted password on the server
- Token instead of password
- Token has to be pre-created for user
- Example implementation:
django-rest-framework-digestauth
JSON Web Token (JWT)
2. Response: HTTP 401 Unauthorized
WWW-Authenticate: JWT realm="api"
1. Request: GET /invoices/
6. Response: HTTP 200 OK
5. Request: GET /invoices/
Authorization: JWT eyJhbGciOiAiSFMyNTYiLCAidHlwIj
4. Response: 200 OK
{"token" : "eyJhbGciOiAiSFMyNTYiLCAidHlwIj"}
3. Request: POST /obtain-auth-token/
{"username": "john", "password": "secretpass"}
JWT Auth
- Client app stores token
- Server does not need to matain tokens
- Server only generates and validates tokens
- Stateless
- JWTs can be signed using a secret
or a public/private key pairs
JWT Auth
{
"alg": "HS256",
"typ": "JWT"
}
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
Header
Payload
Signature
OAuth 2.0 / OpenID
- OAuth 2.0
- Authentication
- Authorization
- OpenID
- Authentication
- OpenID Connect
- Built on the top of OAuth 2.0
OAuth 2.0 / OpenID
- Three roles
- Client app
- Resource server
- Auth server
- Client app needs registering
- Client ID and Secret Token
- Grants are exchanged for access token
Two scenarios
- Providing OAuth protocol
- Follow standards
- Do not build from scratch
- Wrapping other services that provide OAuth
- Keep API Keys and tokens safe
- Do not authenticate on external auth token
What's not here?
- Multi-factor authentication
- HTTP Signature
- HTTP HMAC
- Hawk
- SAML / SSO
Summary
- API keys provide extra layer over passwords
- Auth mechanism should fit to requirements
- Always use HTTPS
- You can support multiple methods
Resources
- https://auth0.com/blog/angularjs-authentication-with-cookies-vs-token/
- https://jwt.io
- https://github.com/hueniverse/hawk
- https://github.com/acquia/http-hmac-spec
- https://github.com/joyent/node-http-signature/blob/master/http_signing.md
- https://aaronparecki.com/2012/07/29/2/oauth2-simplified
- http://www.django-rest-framework.org/api-guide/authentication/
- https://github.com/juanriaza/django-rest-framework-digestauth
We're looking for speakers!
Join the team!
Thanks!
Questions?
@haxoza
Mechanizm uwierzytelnienia dla twojego API
By Przemek Lewandowski
Mechanizm uwierzytelnienia dla twojego API
- 2,992