-
Notifications
You must be signed in to change notification settings - Fork 145
DRAFT: Added /learning-identity section to docs, plus JWT page #1161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
53f1bea
d1fad28
85bdd5a
eb27652
051c6c7
a654dff
d841cef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| --- | ||
| 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. | ||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
| 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. | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| 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). | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||||||
| ``` | ||||||
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.