Skip to content

Add sidebar navigation to introduction page #870

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

Merged
merged 12 commits into from
Aug 8, 2025
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import React from "react";
import { getIntroductionContent } from "@/features/localization/services/ui-language-content.service";
import { ArticleComponent } from "@/features/common/components/article/article.component";
import styles from "./introduction-article.module.scss";
import { SidebarNavComponent } from "../sidebar-nav/sidebar-nav.component";

interface IntroductionArticleComponentProps {
languageCode: string;
Expand All @@ -11,11 +13,12 @@ interface IntroductionArticleComponentProps {
export const IntroductionArticleComponent: React.FC<
IntroductionArticleComponentProps
> = ({ languageCode }) => {
const { Component: Introduction } = getIntroductionContent({ languageCode });
const Introduction = getIntroductionContent({ languageCode });

return (
<ArticleComponent>
<Introduction />
</ArticleComponent>
<div className={styles.container}>
<SidebarNavComponent languageCode={languageCode} />
<ArticleComponent>{Introduction}</ArticleComponent>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@use "@/libs/theme/styles/variables" as *;

.container {
min-height: 100vh;
display: flex;
flex-direction: column;

@media #{$breakpoint-dimension-sm} {
flex-direction: row;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
"use client";

import React, { useEffect, useState } from "react";
import { getIntroductionDictionary } from "@/features/localization/services/language-dictionary.service";
import styles from "./sidebar-nav.module.scss";
import clsx from "clsx";

interface SidebarNavComponentProps {
languageCode: string;
}

const scrollToElementWithOffset = (id: string, offset = 0) => {
const element = document.getElementById(id);
if (element) {
const y = element.getBoundingClientRect().top + window.pageYOffset + offset;
window.scrollTo({ top: y, behavior: "smooth" });
}
};

export const SidebarNavComponent: React.FC<SidebarNavComponentProps> = ({
languageCode,
}) => {
const introductionDictionary = getIntroductionDictionary(languageCode);
const headings = introductionDictionary.content.headings;
const [activeId, setActiveId] = useState<string | null>(null);

useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const id = entry.target.id;
setActiveId(id);
history.replaceState(null, "", `#${id}`);
}
});
},
{
rootMargin: "0px 0px -40% 0px",
threshold: 1,
}
);
const elements = headings
.map((heading) => document.getElementById(heading.id))
.filter(Boolean) as HTMLElement[];
elements.forEach((el) => observer.observe(el));
return () => {
elements.forEach((el) => observer.unobserve(el));
};
}, [headings]);

const handleClick = (id: string) => {
scrollToElementWithOffset(id, -120);
history.replaceState(null, "", `#${id}`);
};

return (
<div className={styles.container}>
<ul className={styles.list}>
{introductionDictionary.content.headings.map((heading, index) => (
<li
key={index}
className={clsx(
styles.title,
activeId === heading.id && styles.title__active
)}
onClick={() => handleClick(heading.id)}
>
{heading.title}
</li>
))}
</ul>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
@use "@/libs/theme/styles/variables" as *;

.container {
display:none;
@media #{$breakpoint-dimension-sm} {
display: inline-block;
height: 100vh;
position: sticky;
color: var(--color_fg_link);
flex-shrink: 0;
top: 0;
padding: 160px 30px 0px;
margin-bottom: 100px;
border-right: 1px solid var(--color_border_bold);
max-width: 250px;
overflow-y: auto;
}
}

.title {
margin-bottom: 36px;
padding-right: 8px;
cursor: pointer;
}

.title__active {
color: var(--color_fg_selected);
border-bottom: 1px solid var(--color_border_selected);
}

.list {
list-style-type: none;
}
14 changes: 7 additions & 7 deletions src/features/introduction/docs/en.introduction.mdx
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { MdxAnchorComponent } from "@/features/common/components/markdown/mdx-anchor.component";
import { MarkdownImage } from "@/features/common/components/markdown/markdown-image";

## What is JSON Web Token?
<h2 id={props.headings[0].id}>{props.headings[0].title}</h2>

JSON Web Token (JWT) is an open standard (<MdxAnchorComponent type="external" href="https://tools.ietf.org/html/rfc7519">RFC 7519</MdxAnchorComponent>) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the **HMAC** algorithm) or a public/private key pair using **RSA** or **ECDSA**.

Although JWTs can be encrypted to also provide secrecy between parties, we will focus on *signed* tokens. Signed tokens can verify the *integrity* of the claims contained within it, while encrypted tokens *hide* those claims from other parties. When tokens are signed using public/private key pairs, the signature also certifies that only the party holding the private key is the one that signed it.

## When should you use JSON Web Tokens?
<h2 id={props.headings[1].id}>{props.headings[1].title}</h2>
Here are some scenarios where JSON Web Tokens are useful:

- **Authorization**: This is the most common scenario for using JWT. Once the user is logged in, each subsequent request will include the JWT, allowing the user to access routes, services, and resources that are permitted with that token. Single Sign On is a feature that widely uses JWT nowadays because of its small overhead and its ability to be easily used across different domains.
- **Information Exchange**: JSON Web Tokens are a good way of securely transmitting information between parties. Because JWTs can be signed—for example, using public/private key pairs—you can be sure the senders are who they say they are. Additionally, as the signature is calculated using the header and the payload, you can also verify that the content hasn't been tampered with.

## What is the JSON Web Token structure?
<h2 id={props.headings[2].id}>{props.headings[2].title}</h2>
In its compact form, JSON Web Tokens consist of three parts separated by dots (`.`), which are:

- Header
Expand Down Expand Up @@ -93,7 +93,7 @@ If you want to play with JWT and put these concepts into practice, you can use <

<MarkdownImage src="https://cdn.auth0.com/website/jwt/introduction/debugger.png" alt="JWT.io Debugger" />

## How do JSON Web Tokens work?
<h2 id={props.headings[3].id}>{props.headings[3].title}</h2>
In authentication, when the user successfully logs in using their credentials, a JSON Web Token will be returned. Since tokens are credentials, great care must be taken to prevent security issues. In general, you should not keep tokens longer than required.

You also <MdxAnchorComponent type="external" href="https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html#local-storage">should not store sensitive session data in browser storage due to lack of security</MdxAnchorComponent>.
Expand All @@ -120,7 +120,7 @@ The following diagram shows how a JWT is obtained and used to access APIs or res

Do note that with signed tokens, all the information contained within the token is exposed to users or other parties, even though they are unable to change it. This means you should not put secret information within the token.

## Why should we use JSON Web Tokens?
<h2 id={props.headings[4].id}>{props.headings[4].title}</h2>

Let's talk about the benefits of **JSON Web Tokens (JWT)** when compared to **Simple Web Tokens (SWT)** and **Security Assertion Markup Language Tokens (SAML)**.

Expand All @@ -138,7 +138,7 @@ _Comparison of the length of an encoded JWT and an encoded SAML_

If you want to read more about JSON Web Tokens and even start using them to perform authentication in your own applications, browse to the <MdxAnchorComponent type="external" href="http://auth0.com/learn/json-web-tokens">JSON Web Token landing page</MdxAnchorComponent> at Auth0.

## Difference Between Validating and Verifying a JWT
<h2 id={props.headings[5].id}>{props.headings[5].title}</h2>

JSON Web Token (JWT) validation and verification are crucial for security, but they address slightly different aspects of JWT security: validation ensures the token is well-formed and contains enforceable claims; verification ensures the token is genuine and unmodified.

Expand All @@ -165,7 +165,7 @@ You verify a JWT to make sure the token hasn't been altered maliciously and come
In many systems, these steps are often combined into what might be colloquially called "JWT verification" which encompasses both validation and verification for comprehensive security checks. Nonetheless, their distinction remains.


## Difference Between Decoding and Encoding a JWT
<h2 id={props.headings[6].id}>{props.headings[6].title}</h2>

Encoding a JWT involves transforming the header and payload into a compact, URL-safe format. The header, which states the signing algorithm and token type, and the payload, which includes claims like subject, expiration, and issue time, are both converted to JSON then Base64URL encoded. These encoded parts are then concatenated with a dot, after which a signature is generated using the algorithm specified in the header with a secret or private key. This signature is also Base64URL encoded, resulting in the final JWT string that represents the token in a format suitable for transmission or storage.

Expand Down
14 changes: 7 additions & 7 deletions src/features/introduction/docs/ja.introduction.mdx
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { MdxAnchorComponent } from "@/features/common/components/markdown/mdx-anchor.component";
import { MarkdownImage } from "@/features/common/components/markdown/markdown-image";

## JSON Web Tokenとは?
<h2 id={props.headings[0].id}>{props.headings[0].title}</h2>

JSON Web Token (JWT) は標準規格(<MdxAnchorComponent type="external" href="https://tools.ietf.org/html/rfc7519">RFC 7519</MdxAnchorComponent>)で定義されています。この仕様は認証、認可の情報をJSON形式でシステム間で安全にやりとりする際に使用できる、コンパクトで自己完結型のフォーマットを定義しています。デジタル署名を付与することもできるため、検証可能で信頼がおけます。JWTへの署名には共通鍵を使用するHMACアルゴリズムあるいは、公開鍵/秘密鍵ペアを使用するRSAまたはECDSAアルゴリズムを使用できます。

JWTは機密性を保つために暗号化することもできますが、ここでは 署名されたJWT に焦点を当てます。署名されたJWTは完全性を検証でき、暗号化されたトークンは内容を他者から隠すことができます。JWTが秘密鍵を用いて署名された場合、その署名は公開鍵を使うことで、秘密鍵を持つ当事者だけがそのJWTに署名した者であることが確認できます。

## JSON Web Tokenはいつ使用すべきか?
<h2 id={props.headings[1].id}>{props.headings[1].title}</h2>
JSON Web Tokenが役立つシナリオをいくつかご紹介します。

- **認証および認可**: JWTを使用する最も一般的な利用用途です。ユーザーがログインすると、その後の各リクエストにはJWTが含まれ、ユーザーはそのJWTで許可されたエンドポイント、リソースにアクセスできます。オーバーヘッドが小さく、異なるドメインのシステム間で簡単に使用できるため、シングルサインオンやSPAやモバイルアプリケーション、APIの呼び出しなどでJWTが使用されています。
- **情報交換**: JSON Web Tokenは、システム間で認証や認可の情報を安全にやりとりする際に優れた形式です。JWTには署名できるため、例えば公開鍵/秘密鍵のペアを使用して、送信者が本人であることを確認できます。さらに、署名はヘッダーとペイロードを使って計算して作成されるため、コンテンツが改ざんされていないことも確認できます。

## JSON Web Tokenの構成は?
<h2 id={props.headings[2].id}>{props.headings[2].title}</h2>
JSON Web Tokenはコンパクトな形態で、ドット(.)で区切られた以下の3つの部分で構成されます。

- ヘッダー
Expand Down Expand Up @@ -93,7 +93,7 @@ JWTを操作してこれらの概念を実際に試したい場合は、<MdxAnch

<MarkdownImage src="https://cdn.auth0.com/website/jwt/introduction/debugger.png" alt="jwt.ioデバッガー" />

## JSON Web Tokenの仕組みとは?
<h2 id={props.headings[3].id}>{props.headings[3].title}</h2>
認証では、ユーザーが資格情報を使用して正常にログインすると、JSON Web Token (JWT)が返されます。トークンは資格情報であるため、セキュリティの問題が起きないように細心の注意を払う必要があります。一般的に、トークンは必要以上に長く保持するべきではありません。

保護されたエンドポイントにユーザーがアクセスしたい場合、ブラウザなどのクライアントはJWTを送信する必要があります。通常は、Bearerスキーマを使用してAuthorizationヘッダーで送信します。したがって、ヘッダーの内容は次のようになります。
Expand All @@ -116,7 +116,7 @@ JWTトークンをHTTPヘッダーで送信する場合は、トークンのサ

署名付きトークンの場合、トークンに含まれるすべての情報は、ユーザーやアクセスを許可をしているサードパーティーに公開されます。その情報が変更されることはありませんが、トークンの中にユーザやサードパーティに知られたくないような機密情報を入れないようにご注意して下さい。

## JSON Web Tokenを使用すべき理由とは?
<h2 id={props.headings[4].id}>{props.headings[4].title}</h2>

**JSON Web Token (JWT)** の利点について、**Simple Web Token (SWT)** および XML を使用する **Security Assertion Markup Language Token (SAML)** と比較してみましょう。

Expand All @@ -134,7 +134,7 @@ _エンコードされたJWTとエンコードされたSAMLの長さの比較_

JSON Web Tokenの詳細や、JSON Web Tokenを使用したアプリケーションの認証については、Auth0の<MdxAnchorComponent type="external" href="http://auth0.com/learn/json-web-tokens">JSON Web Tokenランディングページ</MdxAnchorComponent>をご覧ください。

## JWTのバリデーション(妥当性確認)とベリフィケーション(検証)の違い
<h2 id={props.headings[5].id}>{props.headings[5].title}</h2>

JSON Web Token(JWT)のバリデーション(妥当性確認)とベリフィケーション(検証)はセキュリティ上非常に重要ですが、JWTセキュリティの異なる側面に対応しています。バリデーションはトークンが適切に構成され、強制可能なクレームを含んでいることを確認します。ベリフィケーションはトークンが真正で、変更されていないことを確認します。

Expand All @@ -161,7 +161,7 @@ JSON Web Token(JWT)のバリデーション(妥当性確認)とベリフ
多くのシステムでは、これらの手順は、包括的なセキュリティチェックにおける妥当性の確認と検証の両方を包含する「JWT検証」と呼ばれるものにまとめられることが多々ありますが、両者の区別は存在します。


## JWTのデコーディングとエンコーディングの違い
<h2 id={props.headings[6].id}>{props.headings[6].title}</h2>

JWTのエンコーディングでは、ヘッダーとペイロードをコンパクトでURLに適した形式に変換します。署名アルゴリズムとトークンタイプを記載するヘッダーと、サブジェクト、有効期限、発行時間などのクレームを含むペイロードの両方をJSONに変換しBase64URLエンコードします。これらのエンコードされた部分は、ドット(.)で連結され、その後、ヘッダーで指定されたアルゴリズムを使用して、シークレットキーまたはプライベートキーで署名が生成されます。この署名もBase64URLエンコードされ、送信や保存に適した形式でトークンを表す最終的なJWT文字列が生成されます。

Expand Down
32 changes: 32 additions & 0 deletions src/features/localization/dictionaries/introduction/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,36 @@ export const enIntroductionDictionary: IntroductionDictionaryModel = {
description:
"Learn about JSON Web Tokens, what are they, how they work, when and why you should use them.",
},
content: {
headings: [
{
title: "What is JSON Web Token?",
id: "what-is-json-web-token",
},
{
title: "When should you use JSON Web Tokens?",
id: "when-to-use-json-web-tokens",
},
{
title: "What is the JSON Web Token structure?",
id: "what-is-json-web-token-structure",
},
{
title: "How do JSON Web Tokens work?",
id: "how-json-web-tokens-work",
},
{
title: "Why should we use JSON Web Tokens?",
id: "why-use-json-web-tokens",
},
{
title: "Difference Between Validating and Verifying a JWT",
id: "difference-validating-verifying-jwt",
},
{
title: "Difference Between Decoding and Encoding a JWT",
id: "difference-decoding-encoding-jwt",
},
],
},
};
33 changes: 33 additions & 0 deletions src/features/localization/dictionaries/introduction/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,37 @@ export const jaIntroductionDictionary: IntroductionDictionaryModel = {
description:
"JSON Web Tokenとは何か、どのように機能するのか、いつ、なぜ使用する必要があるのかについて学びましょう。",
},
content: {
headings: [
{
title: "JSON Web Tokenとは?",
id: "what-is-json-web-token",
},
{
title: "JSON Web Tokenはいつ使用すべきか?",
id: "when-to-use-json-web-tokens",
},
{
title: "JSON Web Tokenの構成は?",
id: "what-is-json-web-token-structure",
},
{
title: "JSON Web Tokenの仕組みとは?",
id: "how-json-web-tokens-work",
},
{
title: "JSON Web Tokenを使用すべき理由とは?",
id: "why-use-json-web-tokens",
},
{
title:
"JWTのバリデーション(妥当性確認)とベリフィケーション(検証)の違い",
id: "difference-validating-verifying-jwt",
},
{
title: "JWTのデコーディングとエンコーディングの違い",
id: "difference-decoding-encoding-jwt",
},
],
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,10 @@ import { HeroMetadataModel } from "@/features/common/models/hero-metadata.model"
export interface IntroductionDictionaryModel {
metadata: PageMetadataModel;
hero: HeroMetadataModel;
content: {
headings: {
title: string,
id: string
}[]
}
}
Loading