シングルサインオン (SSO) の簡単ガイド

[![表紙](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/b818bc91-5c9e-19c2-eed4-8473e4ece297.png)](https://leapcell.io/?lc_t=q_sso)

## シングルサインオン (SSO) とは？

フロントエンドシングルサインオン (SSO) は、ユーザーが1つの認証情報セットを使用して複数のアプリケーションやウェブサイトにログインできるようにする認証および認可技術です。これにより、再入力や再登録の必要がなくなり、ユーザーエクスペリエンスが向上し、運用コストが削減され、セキュリティも強化されます。

## シングルサインオンソリューションの概要と実装

フロントエンドSSOの主なアプローチには、以下の方法があります：

### CookieベースのSSO

認証センターでPage Aのログインに成功すると、Cookieが設定されます：
これは最も一般的なSSOの実装方法です。この方式は、ブラウザのCookieメカニズムに基づいています。ユーザーが初めてアプリケーションにログインする際、認証センターにリクエストを送信します。ユーザーの身元を確認した後、認証センターはユーザー情報と有効期限を含む暗号化されたCookieを返します。このCookieのドメインはトップレベルドメイン (例: `example.com`) に設定され、同じトップレベルドメイン配下のアプリケーション (例: `a.example.com` と `b.example.com`) 間で共有されます。他のアプリケーションにアクセスする際、Cookieが有効であるかどうかを確認し、有効であれば直接ログインします。有効でなければ、ユーザーは認証センターにリダイレクトされてログインを求められます。この方法は実装が簡単ですが、同じトップレベルドメイン配下のアプリケーションに限定され、クロスドメインの問題があり、Cookieのサイズや数に制限があります。

Page Aでログイン成功後のCookie設定：

```js
// 暗号化されたCookie値を生成
const encryptedValue = encrypt(userinfo);

// Cookieを設定
document.cookie = `sso_token=${encryptedValue};domain=.example.com;path=/;max-age=86400;`;
```

Page BでCookieを確認：

```js
// Cookieを取得
const cookieValue = document.cookie
  .split(';')
  .find((cookie) => cookie.trim().startsWith('sso_token='))
  .split('=')[1];

// Cookieを復号化
const userinfo = decrypt(cookieValue);

// 直接ログイン
login(userinfo);
```

### トークンベースのSSO

これはステートレスなSSOの実装方法です。この方式では、ユーザーが最初にログインする際に認証センターにリクエストを送信します。ユーザーの身元確認後、認証センターはユーザー情報と有効期限を含む暗号化されたトークンを返します。このトークンはブラウザのローカルストレージ (例: `localStorage` や `sessionStorage`) に保存されます。他のアプリケーションにアクセスする際、トークンが有効かどうかを確認し、有効であれば直接ログインします。有効でなければ、ユーザーは認証センターにリダイレクトされてログインを求められます。この方法はクロスドメイン操作をサポートし、Cookieの制約を受けませんが、追加のストレージスペースとネットワークオーバーヘッドが必要です。また、トークンが盗まれると、身元の悪用につながるリスクがあります。

Page Aでログイン成功後にトークンを`localStorage`に保存：

```js
// トークン値を生成
const token = generateToken(userinfo);

// トークンを保存
localStorage.setItem('sso_token', token);
```

他のページでトークンを確認：

```js
// トークンを取得
const token = localStorage.getItem('sso_token');

// トークンを検証
const userinfo = verifyToken(token);

// 直接ログイン
login(userinfo);
```

### OAuth 2.0ベースのSSO

この方式では、OAuth 2.0のAuthorization Codeフローを使用します。ユーザーが初めてアプリケーションにログインする際、認証センターにリクエストを送信します。認証センターがユーザーの身元を確認した後、認証コードを返し、アプリケーションのコールバックURLにリダイレクトします。その後、アプリケーションは認証センターにコードを送信し、ユーザー情報と有効期限を含むアクセストークンとリフレッシュトークンを取得します。これらのトークンはブラウザのローカルストレージに保存されます。他のアプリケーションにアクセスする際、アクセストークンが有効であれば直接ログインします。有効でなければ、ユーザーは認証センターにリダイレクトされてログインを求められます。この方法はOAuth 2.0標準に準拠し、ウェブ、モバイル、デスクトップなど複数のクライアントタイプをサポートします。ただし、実装が複雑で、複数のリクエストとリダイレクトが必要です。

Page Aで認可リクエストを送信：

```js
const authorizeUrl = `https://auth.example.com/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent(
  redirectUri
)}&response_type=code`;

// 認証ログインページにリダイレクト
window.location.href = authorizeUrl;
```

ログイン成功後にPage AのコールバックURLに認証コードをリダイレクト：

```js
const redirectUri = 'https://app.example.com/callback';

// 認証コードを生成
const code = generateAuthorizationCode(userinfo);

// アプリケーションのコールバックURLにリダイレクト
window.location.href = `${redirectUri}?code=${code}`;
```

Page Aで認証コードをアクセストークンに交換：

```js
const code = getQueryString('code');

// 認証センターにリクエストを送信してアクセストークンを取得
const tokenUrl = `https://auth.example.com/token?client_id=${clientId}&client_secret=${clientSecret}&code=${code}&grant_type=authorization_code`;

fetch(tokenUrl)
  .then((response) => response.json())
  .then((data) => {
    // アクセストークンとリフレッシュトークンを保存
    localStorage.setItem('access_token', data.access_token);
    localStorage.setItem('refresh_token', data.refresh_token);

    // 直接ログイン
    login(data.userinfo);
  });
```

---

### [私たちはLeapcell、Node.jsプロジェクトのホスティングの最適解です——最大100MBのファイルアップロードに対応しています！](https://leapcell.io/?lc_t=q_sso)

[![Leapcell](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/58043ef2-07c9-e888-6991-f01cf4399dd8.png)](https://leapcell.io/?lc_t=q_sso)

[Leapcell](https://leapcell.io/?lc_t=q_sso)は、Webホスティング、非同期タスク、Redis向けの次世代サーバーレスプラットフォームです：

**複数言語サポート**

- Node.js、Python、Go、Rustで開発できます。

**無制限のプロジェクトデプロイ**

- 使用量に応じて料金を支払い、リクエストがなければ料金は発生しません。

**比類のないコスト効率**

- 使用量に応じた支払い、アイドル時間は課金されません。
- 例: $25で6.94Mリクエスト、平均応答時間60ms。

**洗練された開発者体験**

- 直感的なUIで簡単に設定できます。
- 完全自動化されたCI/CDパイプラインとGitOps統合。
- 実行可能なインサイトのためのリアルタイムのメトリクスとログ。

**簡単なスケーラビリティと高パフォーマンス**

- 高い同時実行性を容易に処理するためのオートスケーリング。
- ゼロ運用オーバーヘッド — 構築に集中できます。

[ドキュメントで詳細を確認！](https://docs.leapcell.io/)

[![Try Leapcell](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/3e260136-94b1-5e2b-f411-4b3c17c5ba9f.png)](https://leapcell.io/?lc_t=q_sso)

Xでフォローする：[@LeapcellHQ](https://x.com/LeapcellHQ)

---

[ブログでこの記事を読む](https://leapcell.io/blog/easy-guide-to-sso)