A JSON Web Token (JWT)
is a piece of secure information that is passed from one system to another,
typically a web browser to a server.
It contains enough information to identify some person or other entity,
some claims (properties) about them,
and a digital signature to confirm the information has not been tampered with.
The three bits of the JWT are separated by dots and Base 64 encoded.
Base 64 encoding limits the characters to [A-Z0-9+/] which means the encoding is printable but unreadable.
"sub" (subject) the principal about which the claims are normally made.
"aud" (audience) which must be the name of the API/application.
"exp" (expiry)
"iat" (issued at) which gives the age
An ID token authenticates a user and has information needed to customize a UI, email, picture and phone;
it should not be used to give access to an application.
A access token on the other hand does not authenticate a user but says the bearer of the token has
been given access to the API and perform a set of actions given by the 'scopes'.
{{ structure.payload | prettyJSON }}
Signature
The signature is created from the original header and payload.
If the signature does not match the header and payload in the message then they are not the original.
{{ structure.signature }}
Sig = HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
Browser Storage and Vulnerabilities.
Local storage
In a web browser, each domain and port (URL) has an associated table of key value pairs (of 5MB of storage) called local storage.
This is very easy to use with Javascript:
localStorage.setItem(key, value)
const value = localStorage.getItem(key)
It has no expiry so that when a user re-opens that URL (domain and port) the data will still be there.
It cannot be accessed by other sites with another 'domain and port' or from localhost.
Another user logging into the same machine (e.g. laptop or server) have no access.
Unencrypted data in local storage can be vulnerable to Cross site scripting (XSS) attacks.
On the other hand, since no data is loaded up to the server and it provides a way for an application to work with a user's PPI without
privacy or GDPR compliance issues.
The contents of your current local storage:
Key
Value
{{ key }}
{{ item }}
{{ cookie }}
Session storage
Session storage is like local storage but expires when web browser tabs are closed.
The contents of your current session storage:
Key
Value
{{ key }}
{{ item }}
Cookies
A cookie is created when a server sends a 'Set-Cookie' response header in an HTTP response to a client:
HTTP/2.0 200 OK
Content-Type: text/html
Set-Cookie: cookie_key=cookie_value_up_to_4Kb
Set-Cookie: sid=abc; Expires=Thu 18 Nov 2022 01:01:00 GMT; Secure; HttpOnly
The client sends back all cookies with every subsequent request:
GET /sample_page.html HTTP/2.0
Host: www.example.org
Cookie: cookie_key=cookie_value_up_to_4Kb;sid=abc
The 'Expires' flag helps prevent cookies being reused later in a
session fixation attack.
The 'Secure' flag indicates a cookie can only be sent of HTTPS and never over insecure HTTP, avoiding man in the middle attacks.
The 'HttpOnly' flag indicates that a Javascript program can never see the cookie, helping to avoid XSS attacks.
By default a cookie will only ever be sent to the server/domain it came from, the 'Domain' attribute indicates other domains.
The 'Path' attribute says the cookie will only be sent with requests that have a particular Path in their URL.
With 'SameSite=Strict' the cookie will only be sent to it's origin and never with cross-origin requests.
From Javascript one can get a list of semi-colon separated cookies using 'document.cookie'.
Your current cookies:
Key
Value
{{ key }}
{{ item }}
Java Web Token in Cookies
A JWT can be placed in session storage and sent in the Authorization field of requests.
However, session storage may be vulnerable to XSS attacks.
To avoid this the JWT can be stored as a cookie with the HttpOnly flag,
so that it will be sent with every request to the origin but not be visible to Javascript.
Summary
Session and local storage can only be read on the client side and are <5MB while cookies are < 4KB.
Cookies and session storage have automatic expiry (session storage until browser or tab is closed).
XSS, CSFR and CORS
Cross-site scripting (XSS) allows an attacker to execute arbitrary Javascript within a victim's browser.
The following URL includes Javascript in the query string.
Ideally the website should always 'escape' string properly to avoid these ever being interpretted as code,
unfortunately this is not always done consistently.
In particular since websites rely on so many third party Javascript libraries which may have their own vulnerabilities.
https://insecure-website.com/status?message=<script>... Naughty Javascript Here ...</script>
Reflected XSS
Given a URL: https://insecure-website.com/search?term=stuff
and a web page that displays the search term:
<p>Results for: { term } </p>
Given an attackers URL: https://insecure-website.com/search?term=<script>{ doBadStuff() }</script>
The web page will call the dodgy code:
<p>Results for: <script>{ doBadStuff() }</script> </p>
A CSRF Token is a random string generated by a server and sent to the client.
Each client request would include the CSRF Token so that the server can indeed confirm each request came from the client.
Typically you want to include the CSRF Token in the request body, or a custom header, and not the query string, as the latter are often logged.
Since Cookies are sent automatically with all requests placing a CSRF token in a Cookie,
means it would be sent with all request from the browser including those you don't want ...
Cross-origin requests (CORS)
...
OAuth 2.0 and OpenID Connect
With a traditional client and server model, the developers have to write the application and takes care of authentication and authorization.
With OAuth 2.0 and OpenID Connect, the idea is to decouple identity management so the server just has to worry about providing the application,
while specialist software such Cognito takes care of identity authentication.
Authentication is confirming users are who they say they are while authorization is about saying what they can do.
Authentication is about identity while authorization is about privilleges.
Oauth 2.0
Oauth 2.0 is an authorization standard.
It introduces quite a lot of jargon and terminology that needs to be understood.
A Resource Owner typically an end user but in general any entity that can grant access to a resource.
A Client is the actual application requesting access to the resource which is not necessarilly the end-user client or web-browser.
A User Agent is typically a browser, a program used by the resource owner to access the Client.
An Authorization Server issues Access Tokens (in JWT format) after authenticating the Resource Owners.
A Resource Server hosts the API and protected resource that the Client wants access to, essentially it is the 'application'.
When a Resource Server receives a JWT from a client,
it has to check the signature on the JWT is valud,
that it has not expired and ...
If the the identity is disabled or deleted, there is no way to know this from the JWT,
the Resource Server can either rely on the expiry period being short or go to the expense of asking the Authentication Server.
Space-separated identifiers that say what privilleges or actions are requested.
See RFC 6749.
For example 'email' requests access to email and email_verified claims.
The 'openid' scope is always required.
One can confuse Grant with OpenID Connect Flow.
A flow is a protocol, while I believe a Grant refers only to a credential used withing a flow.
From the specification (RFC 6749):
"An authorization grant is a credential representing the resource owner's authorization ... used by the client to obtain an access token.
This specification defines four grant types -- authorization code, implicit, resource owner password credentials, and client credentials ..."
Open ID Connect
OpenID Connect is an identity layer on top of Oauth 2.0.
A Client can ask an Oauth2.0 Authorization Server to authenticate or verify the identity of an end-user and also return some profile information about the end-user.
Each 'Flow' is different variant of the protocol to get an Access Token from the Authorization Server.
A cron job accessing an API would uses the client id and client secret to get hold of an Access Token but would have no need end-user authorization,
so use the Client Credentials Flow. In this case the Client is the Resource Owner.
If the Client is a web server, use the Authorization Code Flow which passes the Access Token directly to the server without going through the web browser.
If Resource Owner Password Flow can be used if the Client has and can be trusted with the username and password.
If the Client is a Single Page Application (SPA) then use Authorization Code Flow with Proof Key for Code Exchange (PKCE).
If application is a mobile app then can also use Authorization Code Flow with Proof Key for Code Exchange (PKCE).
Security Assertion Markup Language (SAML)
SAML
supports single sign-on (SSO) allowing one set of credentials to login to many websites.
Allows identity providers (IdP) to pass authorization credentials to service providers (SP).
SAML Identity Provider (IdP)
manages identities and sercurity tokens
(known as an Authorization Server in Oath2)
SAML Servicer Provider
the actual application
(known as aResource Server in Oauth2)
Endpoints and Examples
Oauth2 and OpenID Connect define the following
API.
The following bash script provides examples of use:
Symmetric Encrypt and Decrypt with Javascript
This example uses the SubtleCrypto package
for symmetric encryption using AES (Advanced Encryption Standard).
AES modes include: CTR (Counter Mode), CBC (Cipher Block Chaining), GCM (Galois/Counter Mode).
This example uses: CBC.
...
Plain text
Secret
Symmetric encryption means using the same secret/password for both encryption and decryption.
Encrypted Cipher text
Plaintext is the unencrypted text while ciphertext is the encrypted text,
typically ciphertext is binary data and can only be displayed as numbers of random characters.
Decrypted plain text
This is the result for encryption followed by decryption and ought to be identical to the
plaintext above.