Work in progress!
An authentication scheme is a method or recipe to pass credentials from a user to an authenticating system.
Authorization: <authentication type> <credential as base64>
Authorization: Basic <name:password>
Authorization: Bearer <oauth token>
HTTP Basic Authentication
More about this flow here: https://en.wikipedia.org/wiki/Basic_access_authentication#Protocol
Access a resource with a token instead of using a login/password.
i.e. Flickr uses OAuth to allow third-party services to post and edit pictures on their behalf, without them having to give out their flickr username and password.
OpenId vs oAuth
OpenID is intended for federated authentication. A client accepts an identity assertion from any provider (although clients are free to whitelist or blacklist providers).
OAuth is currently better suited for authorization, because further interactions after authentication are built into the protocol, but both protocols are evolving. OpenID and its extensions could be used for authorization, and OAuth can be used for authentication, which can be thought of as a no-op authorization.
The gist is to use the Basic HTTP Authentication, but with a token instead of real credentials.
Typically JWT is sent in the Authorization header using the Bearer schema (hence “bearer token”). But it can also be stored in a cookie or other.
Authorization: Bearer <token>
Bearer tokens; that is, presenting a well-formed, non-expired, non-revoked auth token directly to an endpoint is accepted as sufficient proof of customer authentication.
A request authorization approach in which a token is presented directly to a service endpoint for purposes of establishing identity and/or obtaining access. Because these tokens will grant access to anyone in possession of the token, it is important to protect the confidentiality of these tokens, at rest and in transit (e.g. via access control and/or encryption, such as full-volume encryption, TLS, etc.).
There’s no server-side state associated with bearer tokens, so there’s no way to list all the authenticated sessions.
Access Token and Refresh token
Split token model
Refresh token/access token model, as described in the OAuth 2.0 specification http://tools.ietf.org/html/rfc6749#section-1.4, to achieve a balance of efficiency for services, and support for revocation.
A “token-granting-token,” often issued to a client directly following an authentication. The refresh token is used to obtain access tokens from a token service. Refresh tokens are not (and must not be) sent directly to service endpoints (see below). The refresh token is implemented as a bearer token.
The access token is presented as part of an access/authorization request to a service endpoint, as a bearer token. Access tokens are typically, by design, short-lived, such that a client must obtain a new access token periodically to continue accessing a service endpoint. This provides an opportunity for revocation; for example, when a refresh token is revoked on the server side (e.g., via a password change or “manage my devices” workflow), it can no longer be used to obtain new access tokens. In this case, the client must obtain a new refresh token (usually via an explicit authentication, like entering a password) before obtaining a new access token for use with service endpoints.
JSON Web Token – JWT
Typically sent in the Authorization header using the Bearer schema (see Bearer token).
But can also be stored and set via cookies or other!
Why use a token anyways?
This is important because it is better to pass a token (that can expire, and have limited scope) to your API than a username and password!
If the password is compromised, keys to the castle.
The idea is that you present your hard credentials once, and then get a token to use in place of the hard credentials.
Why is it called JSON Web Token?
B/c it’s a token and it contains JSON. It could be an XML token or other form of token. JWT are famous these days.
JWT tokens are composed of 3 parts.: Header.Body.Signature
The body contains the juicy bits. It is a JSON object giving your information about the user such as roles, etc.
You can save whatever you want inside this object. The default are:
“Sub”: Who this person is (sub, short for subject)
“Scope”: What this person can access with this token (scope)
“Exp”: When the token expires (exp)
“Iss”: Who issued the token (iss, short for issuer)
Every property (key value) inside of this object is a claim.
The header contain information about the token itself.
They can be cryptographically signed and encrypted to prevent tampering on the client side.
Signature hash that can be used to verify the integrity of the token (if you have the secret key that was used to sign it).
JTI Claim = unique ID for a token The jti claim can be used to prevent the JWT from being replayed. The jti value is a case-sensitive string. Use of this claim is OPTIONAL. Json web signature: https://tools.ietf.org/html/rfc7515 Jason web ecnryption: https://tools.ietf.org/html/rfc7516
Tokens Are Signed, Not Encrypted
A JSON Web Token is comprised of three parts: the header, payload, and signature.
The format of a JWT is header.payload.signature.
If we were to sign a JWT with the HMACSHA256 algorithm, the secret ‘shhhh’ and the payload of:
“name” : “Ado Kukic” ,
“admin” : true}
The signature would be:
And the JWT generated would be:
The very important thing to note here, is that, this token is signed by the HMAC SHA 256 algorithm, and the header and payload are Base64URL encoded, it is not encrypted.
If I go to jwt.io, paste this token and select the HMACSHA256 algorithm, I could decode the token and read its contents. Therefore, it should go without saying that sensitive data, such as passwords, should never be stored in the payload.
Is it possible to encrypt the token?
Of course, If you must store sensitive data in the payload or your use case calls for the JWT to be obscured, you can use JSON Web Encryption (JWE). JWE allows you to encrypt the contents of a JWT so that it is not readable by anyone but the server.
JWT’s allow you to store any type of metadata, as long as it’s valid JSON. Stateless, no mapping required server side.
When using the cookie based authentication, the back-end has to do a lookup, whether that be a traditional SQL database or a NoSQL alternative, and the roundtrip is likely to take longer compared to decoding a token. Additionally, since you can store additional data inside the JWT, such as the users permission level, you can save yourself additional lookup calls to get and process the requested data.
Well you can cache too! To avoid database roundtrips.
The biggest disadvantage of token authentication is the size of JWTs. A session cookie is relatively tiny compared to even the smallest JWT.
Where to Store Tokens?
With token-based auth, you are given the choice of where to store the JWT.
Storing the token
2 main ways to store the token, cookies or web storage (local storage).
See Cookies vs LocalStorage.
Cookie vs Local Storage
Why cookies instead of LocalStorage for storing the JWT ?
Ease – Cookies are automatically transferred and a header need not be set. This solves the issue where a service may have it’s own admin page like wallace. If the auth header was required, you will never be able to access the service admin page since browser won’t be able to set the header itself.
Downside with cookies is that they make CSRF attacks.
Cookies are limited to 4KB. You must have a light JWT token (I prefer that!).
So basically why not storing a simple session GUID at the end?
Request the token with your hard credentials:
The response will defer deepening of the storage type.
Web Storage (local storage or session storage)
The respose could be:
HTTP/1.1 200 OK
It’s up to you to call the stprage API to save the token and to retrieve it.
To pass the access token back to your protected APIs, you would use the HTTP Authorization Header and the Bearerscheme.
The request that your SPA would make would resemble:
Authorization: Bearer eyJhbGciOiJIUzI1
The response would use the Set-CookieHTTP header:
HTTP/1.1 200 OK
Set-Cookie: access_token=eyJhbGciOiJIUzI1NiIsI.eyJpc3MiOiJodHRwczotcGxlL.mFrs3Zo8eaSNcxiNfvRh9dqKP4F1cB; Secure; HttpOnly;
To pass the access token back to your protected APIs on the same domain, the browser would automatically include the cookie value. The request to your protected API would resemble:
So, What’s the difference?
Both are stateless because all the information your API needs is in the JWT.
No further check needed (Andrew: technically, it’s better to not overload the JWT but to map the user id to the roles saved in DB etc).
LocalStorage is accessible to JS in the same domain only. Via XSS attacks attackers can easily get local storage info.
Unlike cookies (via HttpOnly) – as a storage mechanism, Web Storage does not enforce any secure standards during transfer.
ALso, whoever reads Web Storage and uses it must do their due diligence to ensure they always send the JWT over HTTPS and never HTTP (as opposed to the Secure flag for Cookies).
If HttpOnly set to True, cannot be accessed through JS.
More flags to increase cookie security over here: Cookies and security.
See XSS – CrosS Site Scripting.
Cross-site request forgery (CSRF). A CSRF attack is a type of attack that occurs when a malicious web site, email, or blog causes a user’s web browser to perform an unwanted action on a trusted site on which the user is currently authenticated.
See Cross-Site Request Forgery – CSRF.