forked from alterminal/alterminal
64 lines
3.1 KiB
Go
64 lines
3.1 KiB
Go
package oidc
|
||
|
||
import (
|
||
"fmt"
|
||
"net/http"
|
||
|
||
"alterminal/internal/application"
|
||
"alterminal/internal/auth"
|
||
)
|
||
|
||
// discoveryMaxAge 為 Discovery 文件的建議快取秒數,與 JWKS 一致:內容
|
||
// 僅在部署設定變更時改變。
|
||
const discoveryMaxAge = 3600
|
||
|
||
// discoveryDocument 為 OIDC Discovery 文件(OIDC Discovery 1.0 §3)。
|
||
// 本服務僅支援授權碼流程(RFC 6749 §4.1.1)與 refresh token grant
|
||
// (§6);subject type 僅 public(sub 對使用者恆為同一值)。
|
||
type discoveryDocument struct {
|
||
Issuer string `json:"issuer"`
|
||
AuthorizationEndpoint string `json:"authorization_endpoint"`
|
||
TokenEndpoint string `json:"token_endpoint"`
|
||
UserInfoEndpoint string `json:"userinfo_endpoint"`
|
||
JWKSURI string `json:"jwks_uri"`
|
||
ScopesSupported []string `json:"scopes_supported"`
|
||
ResponseTypesSupported []string `json:"response_types_supported"`
|
||
ResponseModesSupported []string `json:"response_modes_supported"`
|
||
GrantTypesSupported []string `json:"grant_types_supported"`
|
||
SubjectTypesSupported []string `json:"subject_types_supported"`
|
||
IDTokenSigningAlgValuesSupported []string `json:"id_token_signing_alg_values_supported"`
|
||
TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported"`
|
||
CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported"`
|
||
ClaimsSupported []string `json:"claims_supported"`
|
||
}
|
||
|
||
// DiscoveryHandler 處理 GET /.well-known/openid-configuration:發佈本
|
||
// 服務的 OIDC 端點與能力中繼資料,供 RP 以標準方式取得組態。issuer 於
|
||
// main 讀取 ISSUER 環境變數後注入——issuer 字串須與簽入 token 的 iss
|
||
// claim 完全一致(OIDC Core §3.1.3.7 的 issuer 驗證)。
|
||
func DiscoveryHandler(issuer string) http.HandlerFunc {
|
||
doc := discoveryDocument{
|
||
Issuer: issuer,
|
||
AuthorizationEndpoint: issuer + "/authorize",
|
||
TokenEndpoint: issuer + "/token",
|
||
UserInfoEndpoint: issuer + "/userinfo",
|
||
JWKSURI: issuer + "/.well-known/jwks.json",
|
||
ScopesSupported: application.ScopesSupported(),
|
||
ResponseTypesSupported: []string{"code"},
|
||
ResponseModesSupported: []string{"query"},
|
||
GrantTypesSupported: []string{"authorization_code", "refresh_token"},
|
||
SubjectTypesSupported: []string{"public"},
|
||
IDTokenSigningAlgValuesSupported: []string{"RS256"},
|
||
TokenEndpointAuthMethodsSupported: []string{"client_secret_basic", "client_secret_post", "none"},
|
||
CodeChallengeMethodsSupported: []string{"S256"},
|
||
ClaimsSupported: []string{
|
||
"sub", "iss", "aud", "exp", "iat", "auth_time", "nonce",
|
||
"name", "preferred_username", "email", "email_verified",
|
||
},
|
||
}
|
||
return func(w http.ResponseWriter, r *http.Request) {
|
||
w.Header().Set("Cache-Control", fmt.Sprintf("public, max-age=%d", discoveryMaxAge))
|
||
auth.WriteJSON(w, http.StatusOK, doc)
|
||
}
|
||
}
|