Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions astro/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,11 @@ export default defineConfig({
collapsed: true,
items: [{ autogenerate: { directory: "introspection" } }],
},
{
label: "Learning Identity",
collapsed: true,
items: [{ autogenerate: { directory: "learning-identity" } }],
},
],
}),
redirectFrom({
Expand Down
21 changes: 21 additions & 0 deletions astro/src/content/docs/learning-identity/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
title: Learning Identity
description: Overview of Identity concepts that can be learned in this area of the site.
sidebar:
label: Learning Identity
order: 1
---

import { CardGrid, LinkCard } from "@astrojs/starlight/components";

The concept of Identity spans many topics. This section of documentation is meant to teach the basics of those individual concepts.

## Key Concepts

<CardGrid>
<LinkCard
href="/learning-identity/what-is-a-jwt/"
title="What is a JWT"
description="Overview of what a JWT is and it's structure."
/>
</CardGrid>
27 changes: 27 additions & 0 deletions astro/src/content/docs/learning-identity/jwk.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file feels incomplete, is this all there is?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it was just a starter to show other things we can add in the future.

title: JWKs
description: Overview of what a JWK is, how it can used, and how it differs from a JWT.
sidebar:
label: JWKs
order: 101
---

import { CardGrid, LinkCard } from "@astrojs/starlight/components";

# JWTs

JSON Web Tokens (JWTs) are

They are defined in the IETF's [RFC7519](https://datatracker.ietf.org/doc/html/rfc7519) as an open standard.


## Reading JWTs

JWTs are encoded, and thus are not human readable by default. They must be decoded.

> Note: Encoded does not mean encrypted. Anyone can decode a JWT.





116 changes: 116 additions & 0 deletions astro/src/content/docs/learning-identity/what-is-a-jwt.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
---
title: What is a JWT
description: Overview of what a JWT is and it's structure.
sidebar:
label: What is a JWT
order: 100
---

JSON Web Tokens (JWTs) are JSON formatted strings which contain information about a subject, a human user or some other system like an API service, or AI Agent. The JWT is generated after the subject authenticates with the system by entering their username/password, providing a passkey, or authenticating any other way.

The official standard for JWTs is the IETF's [RFC7519](https://datatracker.ietf.org/doc/html/rfc7519), and we will be referencing it below.

The structure of a JWT follows the JSON Web Signature (JWS) format defined in [RFC7515](https://datatracker.ietf.org/doc/html/rfc7515). This means they are formatted into three sections separated by a dot. Each section is defined below, but they are all self-contained, Base64 URL Encoded strings.

> Reminder: Encoded does not mean encrypted. Anyone can decode a JWT and read the plaintext values. The JWT is Base64 URL Encoded to make it simple to transmit the string between services by avoiding characters that can be problematic on the web, like spaces and quotes.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Astro/Starlight has a way to make this a "note", please see other pages for examples.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will update this. I copy/pasted that from somewhere. I think we need to change a few places to match the correct way.


## Reading JWTs

All programming ecosystems have libraries to parse a JWT, so you don't need to implement the parsing logic yourself, regardless of your technology stack. For the curious, if you want to make your JWT instance human-readable, you can use the [Duende JWT Decoder](https://demo.duendesoftware.com/jwt-decoder).

## Sections of a JWT

The three sections of the JWT are Base64 URL Encoded strings separated by a dot. They are the Header, Payload, and Signature.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The three sections of the JWT are Base64 URL Encoded strings separated by a dot. They are the Header, Payload, and Signature.
The three sections of the JWT are Base64 URL-encoded strings separated by a dot. They are the **Header**, **Payload**, and **Signature**.


An example JWT value `eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk` would be decoded as:
- Header: `{"typ": "JWT", "alg": "HS256"}`
- Payload: `{ "iss": "joe", "exp": 1300819380, "http://example.com/is_root": true }`
- Signature: `dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk`

### Header

The header, also called the JSON Object Signing and Encryption Header (JOSE Header), contains properties describing the cryptographic operations performed to sign the JWT payload. The example below shows that the `HS256` algorithm was used to sign the payload.

```json
{
"alg": "HS256",
"typ": "JWT"
}
```

### Payload

The payload section of the JWT contains the Claims for the subject, which is information about the identity. This includes Registered Claim Names, a set of claims with known meanings, and/or any number of custom claims that are specific to your application(s).

#### Registered Claim Names

Some examples of Registered Claim Names are:
- `sub`: The subject the JWT is for. This can be any string that uniquely identifies the subject, like an email address or GUID.
- `iss`: The issuer of the JWT. This is typically the URI of the system that generated the JWT.
- `iat`: The date/time the JWT was issued. The value is the number of seconds since January 1, 1970.
- `exp`: The date/time the JWT expires. Systems receiving a JWT should not trust one after its expiration time has passed. The value is the number of seconds since January 1, 1970.

The full set of Registered Claim Names are listed in the [JWT RFC](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The full set of Registered Claim Names are listed in the [JWT RFC](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1).
The full set of Registered Claim Names is listed in the [JWT RFC](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@khalidabuhakmeh Are you sure the suggested change is correct pronunciation? If you are, I'll change it. Just sounds weird to me.


#### Custom Claims

Custom Claims are any claims that are specific to your application(s). For example, you can define the `department` claim to be a string that specifies which department the user works for. The actual value is stored in a database and loaded when the user signs in.

> Note: An identity system can add any number of claims. Some systems will add everything it knows about the subject, others will scope them only to the system that will use the JWT.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be turned into a call out component


#### Real World Example

The below example shows a payload with a mix of claims. The `sub` and `exp` are registered claims, and the rest are custom claims used by the consuming application.

```json
{
"sub": "user@example.com",
"exp": 1300819380,
"client_id": "my-frontend",
"department": "I.T.",
"team_name": "core developers",
"scope": [
"admin",
"orders:read",
"inventory:read",
"inventory:write"
]
}
```

> Note: A JWT may contain every claim for a user, making the transmitted string very large. Conversely it can contain a minimum amount of information about the subject. The amount of information contained in the JWT is determined by the service generating it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again, call out component.


### Signature

The signature is used to verify the JWT has not been tampered with since it was created. Because the token is an arbitrary string, the Signature adds trust that the JWT is the same value that it was when it was generated by the identity system (the trusted source of truth). Without verifying the signature, anyone could modify a JWT and get full access to the system.

## Pseudocode Generating a JWT

If it helps to visualize the process of generating a JWT with code, the following pseudocode describes what steps are taken to generate one:

```
//Create the Header and Payload JSON strings
var header = "{ "alg": "HS256", "typ": "JWT" }";
var payload = "{ "sub" : "user@email.com" }";

//Base64 URL Encode the Header and Payload values
var headerBase64 = Base64Encode(header);
var payloadBase64 = Base64Encode(payload);

//Generate the signature
// Create the signature,
// sign it with the algorithm mentioned in the header and using a secret,
// then Base64 URL Encode it
var signature = $"{headerBase64}.{payloadBase64}";
var signingSecret = LoadSigningSecretFromSecureLocation();
var signedSignature = SignWithHmacSha256(signature, signingSecret);
var signedSignatureBase64 = Base64Encode(signedSignature);

var jwt = $"{headerBase64}.{payloadBase64}.{signedSignatureBase64}";
print(jwt);
```

With the output looking something like:
```text
eyJhbGciOiJSUzI1NiIsImtpZCI6IkNEMzFENUE3NzVBQkI4MTU0REFGODRCMEEwMzM5MUMxIiwieDV0IjoiZGJLb1RyTDV6M0U4elR3UmdFbHlYc0tFbTcwIiwidHlwIjoiYXQrand0In0.eyJpc3MiOiJodHRwczovL2RlbW8uZHVlbmRlc29mdHdhcmUuY29tIiwibmJmIjoxNzg0MjMzMDU4LCJpYXQiOjE3ODQyMzMwNTgsImV4cCI6MTc4NDIzNjY1OCwiYXVkIjoiYXBpIiwic2NvcGUiOlsiYXBpIl0sImNsaWVudF9pZCI6Im0ybSIsImp0aSI6IkVDMjgwOTkwMkQ3NjIxRjYzNTBCMTU0NDBCNjFGRENBIn0.Q9ULRZ7sIN2HQ_7mzdS2JHqNQeD8duor6z6aUZIO3JwKK1iuRamahCiOXnQLxX7CJd0hnnP6b1K5ivXpAWhuwVSJcAbobyyKs1ihzcTxCvQPurEYDzQYWm_oIMgL5LI4uIUop7k9N2odHTZakustt97yVFDHWV0Zm9MMrTbf6kj-LnohPZlvv7YuByj9KlPZbD88n58hxYeK3_u3xdPpuHIoJWQT-RKzH_hd-WAN4ZkI5Tx4x8riuR9jsQRu2SsdSjGcR-cTwUHimlSaoaz8bhx5v-gr-8WGAWn7JVwA8ieBeLDiHyBmJz52W1qipO67aif7Sb-ky2TjnwvqYglgMg
```
Loading