OIDC シングルサインオンカスタムドメイン置き換え手順(デプロイメントプラン URL 置き換え方式、非推奨)¶
概要¶
Guance デプロイメントプランは、OIDC プロトコルに基づくカスタムドメインアドレス置き換えによるシングルサインオンをサポートしており、ワークスペースのカスタムドメイン方式で OIDC ログインを導入する場合に使用します。
!!! warning
この方式は、新規の導入シナリオでは推奨されなくなりました。
現在は[カスタム OIDC 導入(デプロイメントプラン)](./oidc-custom-access.md) を使用し、Func 内でログインアドレス、`redirect_uri`、コールバックアドレス、ユーザー情報のフォーマット処理を一元的に行うことを推奨します。この方式は、単一 IDP、複数 IDP、および各種非標準 OIDC 互換シナリオにより適しています。
このドキュメントは、既存環境のメンテナンスや過去の設定との互換性のために残されています。
概念¶
| 用語 | 説明 |
|---|---|
| loginUrl | Guance OIDC ログインエントリアドレス。通常は http://ドメイン/oidc/login、またはクエリパラメータを含む形式 |
| authUrl | アカウント認証アドレス |
| callbackURL | アカウント認証成功後に Guance へコールバックするアドレス。通常は http://ドメイン/oidc/callback |
| redirect_uri | authUrl に含まれるコールバックアドレスパラメータ名 |
操作手順¶
1、OIDC 基本設定¶
1)Guance Launcher の ネームスペース:forethought-core > core で、OIDCClientSet 設定項目に子設定項目 requestSet を追加します。
# OIDC クライアント設定(この設定項目に wellKnowURL が設定されている場合、KeyCloakPassSet 設定項目は自動的に無効になります)
OIDCClientSet:
# OIDC Endpoints 設定アドレス、つまり完全な `https://xxx.xxx.com/xx/.well-known/openid-configuration` アドレス
wellKnowURL: https://xxx.xxx.com/xx/.well-known/openid-configuration
# 認証サービスから提供される クライアントID
clientId: xxx
# クライアントの Secret key
clientSecret: xxxx
# 以下はカスタム設定部分(oidc フロー内の各種アドレスをカスタム設定するため)そのままコピー可能
requestSet:
login:
redirectUriFormatRequest:
# ここでスイッチをオンにします
isOpen: true
url: "func 内の関数リクエストアドレス(後述の redirect_uri_format 関数の外部リンクに対応)"
urlFormatRequest:
# スイッチ、デフォルトはオフ
isOpen: true
url: "func 内の関数リクエストアドレス(後述の login_auth_url_format 関数の外部リンクに対応)"
callback:
redirectUriFormatRequest:
# スイッチ、デフォルトはオフ
isOpen: true
description: "login 配下の redirectUriFormatRequest と同様の設定説明"
url: "func 内の関数リクエストアドレス(後述の redirect_uri_format 関数の外部リンクに対応)"
urlFormatRequest:
# スイッチ、デフォルトはオフ
isOpen: true
url: "func 内の関数リクエストアドレス(後述の callback_url_format 関数の外部リンクに対応)"
補足説明:
- 新規導入の場合は、カスタム OIDC 導入(デプロイメントプラン) を使用し、アドレスフォーマット処理を Func に集約することを推奨します。
OIDCClientSet.clientSecretは、設定に直接記述する以外にも、Func 側のパスワードタイプ環境変数を使用して安全に管理し、スクリプトやサンプルコードに機密情報を平文で記述しないようにしてください。
1、redirect_uri_format 関数の説明¶
OIDC フロー全体で非標準の redirect_uri 変更が発生する場合、外部関数でフォーマット処理を行います。login と callback リクエスト時に、oidc クライアント内の redirect_uri が一致していることを確認してください。一致しない場合、クライアント側での state と code の検証が失敗します。
# リクエストメソッド: post
# リクエストボディ内容:
{
"type": "login", # 変更が login と callback のどちらのフローに対応するかを示します
"redirect_uri": "元の redirect_uri アドレス",
"args": {
# oidc/login リクエストで受信したクエリパラメータ
},
"headers": {
# oidc/login リクエストで受信したリクエストヘッダーデータ
}
}
# レスポンス内容:
{
"redirect_uri": "変更後の redirect_uri",
}
2、login_auth_url_format 関数の説明¶
oidc/login のリダイレクトアドレスを外部関数に転送し、再ラップしてからアドレスリダイレクトを実行します。
# リクエストメソッド: post
# リクエストボディ内容:
{
"type": "login", # ログインタイプです。login はログインからのリクエスト、callback はコールバックからのリクエストを示します
"url": "元の OIDC ログインアドレス",
"args": {
# oidc/login リクエストで受信したクエリパラメータ
},
"headers": {
# oidc/login リクエストで受信したリクエストヘッダーデータ
}
}
# レスポンス内容:
{
"url": "フォーマット後の auth_url",
}
3、callback_url_format 関数の説明¶
oidc/callback のリダイレクトアドレスを外部関数に転送し、再ラップしてからアドレスリダイレクトを実行します。
# リクエストメソッド: post
# リクエストボディ内容:
{
"type": "callback", # ログインタイプです。callback からのフローリクエストを示します
"url": "元の生成されたリダイレクトアドレス",
"args": {
# oidc/login リクエストで受信したクエリパラメータ
},
"headers": {
# oidc/login リクエストで受信したリクエストヘッダーデータ
}
}
# レスポンス内容:
{
"url": "フォーマット後の url",
}
2、内蔵 Func にスクリプトを追加¶
注意: このスクリプトはそのままコピー可能です
!!! warning
以下のスクリプトは、アドレスフォーマット処理のロジックを示すためのものです。
スクリプト内に `clientSecret`、Token、その他の機密情報を直接ハードコードしないでください。鍵情報が必要な場合は、Func 側のパスワードタイプ環境変数を使用して注入および読み取りを行ってください。
import json
import copy
import requests
from urllib.parse import urlparse, parse_qs, urlencode, urlunparse
from collections import OrderedDict
def parse_url(url):
'''
url を解析し、統一された url 解析オブジェクトとクエリパラメータの辞書データを返します
'''
# url 情報を解析
parsed_url = urlparse(url)
# ドメインは url パラメータに含めて渡します
query_params = parse_qs(parsed_url.query)
# パラメータの元の順序を保持するために OrderedDict を使用
ordered_params = OrderedDict(query_params)
return parsed_url, ordered_params
def __make_redirect_uri(url, headers):
'''
リクエストヘッダーからリクエスト元アドレスを抽出します。このアドレスは X-Forwarded-Host ヘッダーから抽出します
'''
# redirect_uri を解析
parsed_url, ordered_params = parse_url(url)
x_host = headers.get("X-Forwarded-Host")
x_port = headers.get("X-Forwarded-Port")
x_scheme = headers.get("X-Forwarded-Scheme", "").lower()
if not x_scheme:
x_scheme = copy.deepcopy(parsed_url.scheme)
netloc = copy.deepcopy(parsed_url.netloc)
if x_host:
if (x_scheme == "http" and x_port == "80") or (x_scheme == "https" and x_port == "443"):
netloc = x_host
else:
netloc = f"{x_host}:{x_port}" if x_port else x_host
parsed_url = parsed_url._replace(scheme=x_scheme, netloc=netloc)
new_url = urlunparse(parsed_url)
return new_url
@DFF.API('redirectUriFormatRequest 関数に対応 - oidc クライアント内の redirect_uri 情報をフォーマット')
def redirect_uri_format(**kwargs):
'''
Guance OIDC フローと連携する際に、非標準フローが原因で redirect_uri パラメータ名やパラメータ値が変更される場合、本関数で処理します。
Parameters:
type {str} 現在の操作が oidc フローのどのタイプに対応するか。login は oidc/login リクエストによるアドレス変更、callback は oidc/callback フローによるリクエストを示します
redirect_uri {str} 元の redirect_uri アドレス
args {json} フローに対応するリクエスト内のクエリパラメータ
headers {json} フローに対応するリクエストヘッダー内の情報
return {"redirect_uri": "変更後の redirect_uri アドレス"}
'''
print("kwargs--->>>", json.dumps(kwargs))
# 元の redirect_uri アドレスとリクエストヘッダー情報を抽出
redirect_uri = kwargs.get("redirect_uri", "")
headers = kwargs.get("headers", {})
# 新しい redirect_uri アドレスを生成
new_url = __make_redirect_uri(redirect_uri, headers)
result = {
# このアドレスは元のログイン認証コード取得アドレスを提供します
"redirect_uri": new_url,
}
print("result-->>", result)
return result
@DFF.API('urlFormatRequest 関数に対応 - login 内のリダイレクトアドレス情報をフォーマット')
def login_auth_url_format(**kwargs):
'''
Guance OIDC フローと連携する際に、非標準フローが原因で login アドレス内のパラメータを変更する必要がある場合、本関数で処理できます。
Parameters:
type {str} 現在の操作が oidc フローのどのタイプに対応するか。login は oidc/login リクエストによるアドレス変更、callback は oidc/callback フローによるリクエストを示します
url {str} 元の url アドレス
args {json} フローに対応するリクエスト内のクエリパラメータ
headers {json} フローに対応するリクエストヘッダー内の情報
return {"url": "変更後の url アドレス"}
'''
print("kwargs--->>>", json.dumps(kwargs))
url = kwargs.get("url")
new_url = None
args = kwargs.get("args")
headers = kwargs.get("headers")
new_host = headers.get("X-From")
if new_host:
# url 情報を解析
parsed_url = urlparse(url)
parsed_url = parsed_url._replace(netloc=new_host)
new_url = urlunparse(parsed_url)
result = {
# このアドレスは元のログイン認証コード取得アドレスを提供します
"url": new_url or url
}
print("result-->>", result)
return result
@DFF.API('urlFormatRequest 関数に対応 - callback 内のリダイレクトアドレス情報をフォーマット')
def callback_url_format(**kwargs):
'''
Guance OIDC フローと連携する際に、非標準フローが原因で callback 後に Guance ワークスペースにログインするためのアドレス内のパラメータを変更する必要がある場合、本関数で処理できます。
Parameters:
type {str} 現在の操作が oidc フローのどのタイプに対応するか。login は oidc/login リクエストによるアドレス変更、callback は oidc/callback フローによるリクエストを示します
url {str} 元の url アドレス
args {json} フローに対応するリクエスト内のクエリパラメータ
headers {json} フローに対応するリクエストヘッダー内の情報
return {"url": "変更後の url アドレス"}
'''
print("kwargs--->>>", json.dumps(kwargs))
type = kwargs.get("type")
url = kwargs.get("url")
args = kwargs.get("args") or {}
headers = kwargs.get("headers") or {}
new_url = None
from_v = args.get("from")
if from_v:
# url を解析
parsed_url, ordered_params = parse_url(url)
ordered_params["from"] = from_v
# クエリ文字列を再構築し、元の順序を保持
new_query_string = urlencode(ordered_params, doseq=True)
parsed_url = parsed_url._replace(query=new_query_string)
new_url = urlunparse(parsed_url)
result = {
# このアドレスは callback 成功後にフロントエンドにログインするためのアドレス調整を提供します
"url": new_url or url,
}
return result
注意:redirect_uri_format、login_auth_url_format、callback_url_format の3つの関数に対して、認証リンクの有効化 が必要です。