This content originally appeared on DEV Community and was authored by Dalibor Kundrat
Identity and security overview
When it comes to security. There is a lot of guidance and also advice and commentary on why you should or should not use each approach. It's hard to understand all the different options and security issues they have.
You also have different clients (mobile/web/app) and each has different security requirements for managing, storing and processing data in the form of tokens, cookies or sessions.
At the end, your app may scale and not all options can be deployed as multiple instance nodes without additional changes to the app and infrastructure.
This means that you really need to make decisions at the beginning and ask questions like: What are your customers? and What are your requirements? and What can be added to the system in the future? and How is it possible to deal with the chosen approach? etc. etc..
This article is part of opensource training.
Authentication vs Authorization
-
Authentication
- process of verifying who a user is (identity). -
Authorization
- process of checking what a user has access to (checking permissions to access a particular resource).
Tokens vs Cookie and Sessions
Tokens, cookies and sessions can be interpreted as resources or tools used by various protocols/standards/patterns (OAuth, OpenID, BFF) to perform identity-related tasks.
It is important to understand the basics as they end up being used in combination with the environment, clients used and security level.
In the end, you can wrap the JWT token in a cookie and use it with session data for 'authorization' and 'authentication'.
Cookies
Cookies can be understood as small blocks of data created by the server that are written once in the response and automatically resent with each subsequent request from the web browser until their lifetime expires.
They can be used for authentication/authorization or tracking and marketing purposes. And much more...
IndentityServer cookies example:
There are 3 main properties of cookies:
-
HttpOnly
- An http-only cookie cannot be accessed by client-side APIs, such as JavaScript. The browser will not allow you to access this cookie from the front-end code. -
Secure
A secure cookie can only be transferred over an encrypted HTTPS connection. -
SameSite
3 option valuesStrict
,Lax
orNone
- this tells the browser which domain and address the cookie can be sent to.
What is origin?
The origin is usually ip and port or domain name and subdomain name.
// This are different origins since subdomain are different
https://developer.mozilla.org
https://mozilla.org
// This are also different origins since port number is different
https://localhost:5001
https://localhost:7001
Another cookie definitions:
-
Session cookies
- Created only for the browser session (in memory) and deleted/lost after closing. -
Third-party cookies
- Usually the domain attribute of a cookies matches the domain displayed in the address bar of the web browser. asfirst-party cookies
. Thethird-party cookies
does not match the current domain and is used astracking cookies
to track user activity.
Sessions
Session is used to temporarily store information on the server for use across multiple pages of the site. It is usually associated with a cookie that is used to identify the session stored on the server, but does not contain any data.
Tokens
Tokens are data elements that allow application systems to perform the authorization and authentication process. They are usually encoded as base64 strings.
There are several types of tokens:
-
access token
- Includes user claims and signs them with a secret. It uses JWT tokens. -
refresh token
- Used to "refresh " and get a new 'access token' after its lifetime expires. -
id token
- JSON encoded data about user profile information - etc, etc...
JWT Tokens
JSON Web Token is an open standard that defines how information can be securely transferred between parties as a JSON object.
They are used for authorization
and information exchange
as they provide a security proof that the information wrapped in them is valid and written by a trusted source.
You can easily write arbitrary data to tokens, sign that data, and then have clients use it to access server resources. The server can verify that the token was signed and is still valid.
Basic JWT token flow example:
JWT content:
JWT consist of 3 parts:
-
Header
- Contains information such as the type of token (JWT) and the signing algorithm used, e.g. HMAC SHA256 or RSA.{ "alg": "HS256", "typ": "JWT" }
-
Payload
- Securly signed data (claims)
{ "sub": "1234567890", "name": "John Doe", "admin": true }
-
Signature
- Encrypted header, the encrypted payload, a secret and signed by an algorithm specified in the header.
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret
More additional info about JWT tokens can be found at: official documentation.
The most commonly used token for authorizing access to APIs is the
Bearer
token.
Identity protocols
There are several protocols/specifications available to manage your identity or authorization process.
This was necessary to standardize authentication and authorization between services and clients. So we can use different global identity/authentication providers like Facebook, Google (external/internal) and also standardize the way the process is implemented.
This demo focuses on the most commonly used protocols OAuth
and OpenID Connect
.
Both protocols use a JWT token by default to encrypt and sign sensitive data, or to verify that the request was sent from a trusted source. It is also possible to use cookies on the front end and let the back end do the session and token authorization for you.
You can also watch and learn from various talks:
- OAuth 2.0 and OpenID Connect - [Nate Barbettini]
- Introduction to OAuth 2.0 and OpenID Connect - [Philippe De Ryck]
OAuth
Primarily used to authorize an app's access to a specific resource. This is done without having to share your password with external sites.
If you have ever signed in to a new app and agreed to access your contacts, calendar, etc., you have used OAuth 2.0. This protocol does not provide any information about the user's endpoint, just a token to access certain resources. You can read more about OAuth at this document.
OAuth generally provides clients with "secure delegated access " to certain resources. Imagine you are a Google user and an app wants to access your calendar data. This can be an example of a flow:
OAuth
flow example:
In the above example, an application like Slack, Jira, etc. only gets permission to access a specific resource (e.g. the calendar), but not the user itself, so profile data like username and email are not transferred and remain protected.
If you want to learn more about OAuth, you can watch the following presentations:
Token exchange flows
There are several ways in which grant
can be substituted. The choice depends on what kind of client is requesting access and how much that client is trusted.
- Authorization code flow
- Flow of authorization code with PKCE
- Implicit Flow
- Client credentials flow
Image from Okta
OpenID Connect
OpenID is a protocol for decentralized authentication
A login used by multiple internal/external applications. If you used your Google or Facebook etc. to log in to an external web or app, then you used OpenID Connect
.
OpenID Connect is based on OAuth 2.0. (OAuth is the underlying protocol and OpenId is the identity layer built on top of it) and also uses a JWT token called id_token
which encapsulates identity claims in JSON format. For more information about OpenId, see under this specification.
id_token
example:
{
"iss": "http://server.example.com",
"sub": "248289761001",
"aud": "s6BhdRkqt3",
"nonce": "n-0S6_WzA2Mj",
"exp": 1311281970,
"iat": 1311280970,
"name": "Dalibor Kundrat",
"given_name": "Dalibor",
"family_name": "Kundrat",
"gender": "male",
"birthdate": "0000-10-31",
"email": "d.kundrat@example.com",
"picture": "http://example.com/somepicture_of_dalibor.jpg"
}
OpenId
flow example:
There are several flows that can be used with OpenId
. You can read more about them under this article.
Each OpenId
server by specification provides multiple endpoints to interact with.
The URLs of all endpoints can be explored using the global discovery endpoint. Often referred to as disco. It is available under the path: /.well-known/openid-configuration
and returns JSON OpenID Connect metadata related to the specified authorization server.
Example disco response:
{
"issuer":"https://localhost:5001",
"jwks_uri":"https://localhost:5001/.well-known/openid-configuration/jwks",
"authorization_endpoint":"https://localhost:5001/connect/authorize",
"token_endpoint":"https://localhost:5001/connect/token",
"userinfo_endpoint":"https://localhost:5001/connect/userinfo",
"end_session_endpoint":"https://localhost:5001/connect/endsession",
"check_session_iframe":"https://localhost:5001/connect/checksession",
"revocation_endpoint":"https://localhost:5001/connect/revocation",
"introspection_endpoint":"https://localhost:5001/connect/introspect",
"device_authorization_endpoint":"https://localhost:5001/connect/deviceauthorization",
"frontchannel_logout_supported":true,
"frontchannel_logout_session_supported":true,
"backchannel_logout_supported":true,
"backchannel_logout_session_supported":true,
"scopes_supported":["profile","openid","email","role", "offline_access" //etc..],
"claims_supported":["name","family_name","profile","email", etc..],
"grant_types_supported":["authorization_code","client_credentials", "refresh_token", //etc..],
"response_types_supported":["code","token", "id_token","id_token token" //etc..],
"response_modes_supported":["form_post","query","fragment"],
"token_endpoint_auth_methods_supported":["client_secret_basic","client_secret_post" ],
"id_token_signing_alg_values_supported":["RS256"],
"subject_types_supported":["public" ],
"code_challenge_methods_supported":["plain","S256"],
"request_parameter_supported":true,
"request_object_signing_alg_values_supported":["RS256","RS384" //etc..],
"authorization_response_iss_parameter_supported":true
}
Main OpenId endpoints:
-
/authorization_endpoint
- interacting with the resource owner and obtaining an authorization permission. -
/token_endpoint
- Obtain an access and/or ID token by presenting an authorization permission (code) or refresh token -
/revocation_endpoint
- Revoke an access or refresh token. -
/end_session_endpoint
- Ends the session associated with the specified ID token. -
/userinfo_endpoint
- Provides information about the authenticated end user.
⠀
NOTE: All of these values in the discovery endpoint refer to the current server configuration. You can adjust or enable/disable certain options in your code during idnetityserver configuration.
⠀
Backend for Frontend pattern (BFF)
BBF is a backend used by a particular front-end application.
Since endpoint APIs may have multiple clients with different requests, BFF can provide a client-specific backend mediator and act as a proxy that forwards and merges multiple requests to different service APIs.
⠀
Ok, we have cookies, tokens, and sessions. We use them for various authentication/authorization protocols (OpenId, OAuth, etc.) and what the hack BFF is good for.?Answer is:
- Security reasons
- Architecture reasons ⠀
Security reasons
In recent years, it was common to implement OpenID Connect for SPAs in Javascript (React, Angular, Vue...), and this is no longer recommended:
- Using access tokens in the browser has more security risks than using secure cookies.
- A SPA is a public client and cannot keep a secret, as such a secret would be part of the JavaScript and could be accessible to anyone inspecting the source code.
- Recent browser changes to prevent tracking may result in 'third-party cookies' being dropped.
- It is not possible to store something securely in the browser for a long period of time, as it can be stolen by various attacks.
Due to the above issues, the best security recommendation for SPA is to avoid storing tokens in the browser and create a lightweight backend to help with this process, called Backend for Frontend pattern (BFF).
This way, you can still use acces_tokens
to authorize access to all your APIs, but clients can use cookies or tokens, for example, depending on the type (browser, mobile device), as required for security reasons.
BFF can be:
-
statefull
- stores tokens in memory and uses a session to manage them. -
stateless
- stores the tokens in encrypted HTTP-only, same-page cookies.
Architectural reasons
When you design your application, you have several options on how to access APIs from clients (web/mobile/external).
1) A single API gateway that provides a single API for all clients
2) A single API gateway that provides an API for each type of client
3) A per-client API gateway that provides an API to each client.
BFF vs API gateway
While an API Gateway
is a single entry point into to the system for all clients, a BFF
is only responsible for a single type of client.
BBF cookies termination and token isolation
As mentioned in the text, the most important thing:
- Avoid storing tokens in the browser. (No tokens in the browser policy).
- Store tokens on the server side and use encrypted/signed HTTP-only cookies.
Recommended BFF pattern to secure SPA frontends:
- Using this, all communication from the SPA frontend to the authorization server now passes through the BFF and tokens do not reach the SPA.
- The BFF now issues session cookies. These are part of the request to APIs and are exchanged for an access token at the proxy level.
- Client-side cookies are terminated by the BFF proxy.
Repository
You can find the full source code of the app, including identity, distributed logging, tracing and monitoring, in the open source Github repo:
https://github.com/damikun/trouble-training
This content originally appeared on DEV Community and was authored by Dalibor Kundrat
![](https://www.radiofree.org/wp-content/plugins/print-app/icon.jpg)
Dalibor Kundrat | Sciencx (2021-10-19T22:21:51+00:00) Web App Security, Understanding the Meaning of the BFF Pattern. Retrieved from https://www.scien.cx/2021/10/19/web-app-security-understanding-the-meaning-of-the-bff-pattern/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.