1
0
forked from baron/baron-sso

headless login으로 리펙토링

This commit is contained in:
Lectom C Han
2026-04-01 10:50:31 +09:00
parent d9b0ec410c
commit 94362bf8eb
15 changed files with 276 additions and 127 deletions

View File

@@ -1728,7 +1728,7 @@ func (h *AuthHandler) loadHeadlessJWKS(ctx context.Context, client domain.HydraC
}
raw = body
default:
return nil, fmt.Errorf("trusted rp public key is not configured")
return nil, fmt.Errorf("headless login public key is not configured")
}
var keySet jose.JSONWebKeySet
@@ -1736,7 +1736,7 @@ func (h *AuthHandler) loadHeadlessJWKS(ctx context.Context, client domain.HydraC
return nil, fmt.Errorf("failed to decode jwks: %w", err)
}
if len(keySet.Keys) == 0 {
return nil, fmt.Errorf("trusted rp jwks has no keys")
return nil, fmt.Errorf("headless login jwks has no keys")
}
return &keySet, nil
}

View File

@@ -172,7 +172,7 @@ func TestPollEnchantedLink_ExpiredToken_ReturnsCode(t *testing.T) {
assert.Equal(t, "expired_token", got["code"])
}
func TestHeadlessLinkInit_TrustedClientSuccess(t *testing.T) {
func TestHeadlessLinkInit_HeadlessLoginClientSuccess(t *testing.T) {
redis := &mockRedisRepo{data: make(map[string]string)}
privateKey, jwks := mustHeadlessRSAJWK(t)
@@ -186,7 +186,7 @@ func TestHeadlessLinkInit_TrustedClientSuccess(t *testing.T) {
_ = json.NewEncoder(w).Encode(domain.HydraLoginRequest{
Challenge: "challenge-123",
Client: domain.HydraClient{
ClientID: "trusted-rp",
ClientID: "headless-login-client",
TokenEndpointAuthMethod: "none",
Metadata: map[string]interface{}{
"status": "active",
@@ -215,8 +215,8 @@ func TestHeadlessLinkInit_TrustedClientSuccess(t *testing.T) {
t.Setenv("USERFRONT_URL", "http://userfront.test")
body, _ := json.Marshal(map[string]string{
"client_id": "trusted-rp",
"client_assertion": mustHeadlessClientAssertion(t, privateKey, "trusted-rp", "http://example.com/api/v1/auth/headless/link/init"),
"client_id": "headless-login-client",
"client_assertion": mustHeadlessClientAssertion(t, privateKey, "headless-login-client", "http://example.com/api/v1/auth/headless/link/init"),
"loginId": "010-1234-5678",
"login_challenge": "challenge-123",
})
@@ -248,7 +248,7 @@ func TestHeadlessLinkPoll_AfterApprovalReturnsRedirect(t *testing.T) {
_ = json.NewEncoder(w).Encode(domain.HydraLoginRequest{
Challenge: "challenge-123",
Client: domain.HydraClient{
ClientID: "trusted-rp",
ClientID: "headless-login-client",
TokenEndpointAuthMethod: "none",
Metadata: map[string]interface{}{
"status": "active",
@@ -284,8 +284,8 @@ func TestHeadlessLinkPoll_AfterApprovalReturnsRedirect(t *testing.T) {
t.Setenv("USERFRONT_URL", "http://userfront.test")
initBody, _ := json.Marshal(map[string]string{
"client_id": "trusted-rp",
"client_assertion": mustHeadlessClientAssertion(t, privateKey, "trusted-rp", "http://example.com/api/v1/auth/headless/link/init"),
"client_id": "headless-login-client",
"client_assertion": mustHeadlessClientAssertion(t, privateKey, "headless-login-client", "http://example.com/api/v1/auth/headless/link/init"),
"loginId": "010-1234-5678",
"login_challenge": "challenge-123",
})
@@ -318,8 +318,8 @@ func TestHeadlessLinkPoll_AfterApprovalReturnsRedirect(t *testing.T) {
assert.Equal(t, http.StatusOK, resp.StatusCode)
pollBody, _ := json.Marshal(map[string]string{
"client_id": "trusted-rp",
"client_assertion": mustHeadlessClientAssertion(t, privateKey, "trusted-rp", "http://example.com/api/v1/auth/headless/link/poll"),
"client_id": "headless-login-client",
"client_assertion": mustHeadlessClientAssertion(t, privateKey, "headless-login-client", "http://example.com/api/v1/auth/headless/link/poll"),
"pendingRef": pendingRef,
})
req = httptest.NewRequest(http.MethodPost, "/api/v1/auth/headless/link/poll", bytes.NewReader(pollBody))

View File

@@ -284,7 +284,7 @@ func TestPasswordLogin_OIDC_Success(t *testing.T) {
}
}
func TestHeadlessPasswordLogin_TrustedClientSuccess(t *testing.T) {
func TestHeadlessPasswordLogin_HeadlessLoginClientSuccess(t *testing.T) {
mockIdp := new(MockIdentityProvider)
mockIdp.On("SignIn", "employee001", "password").Return(&domain.AuthInfo{
SessionToken: &domain.Token{JWT: "valid-jwt"},
@@ -305,7 +305,7 @@ func TestHeadlessPasswordLogin_TrustedClientSuccess(t *testing.T) {
json.NewEncoder(w).Encode(domain.HydraLoginRequest{
Challenge: "challenge-123",
Client: domain.HydraClient{
ClientID: "trusted-rp",
ClientID: "headless-login-client",
TokenEndpointAuthMethod: "none",
Metadata: map[string]interface{}{
"status": "active",
@@ -339,11 +339,11 @@ func TestHeadlessPasswordLogin_TrustedClientSuccess(t *testing.T) {
clientAssertion := mustHeadlessClientAssertion(
t,
privateKey,
"trusted-rp",
"headless-login-client",
"http://example.com/api/v1/auth/headless/password/login",
)
body, _ := json.Marshal(map[string]string{
"client_id": "trusted-rp",
"client_id": "headless-login-client",
"client_assertion": clientAssertion,
"loginId": "employee001",
"password": "password",
@@ -390,7 +390,7 @@ func TestHeadlessPasswordLogin_MissingClientAssertionRejected(t *testing.T) {
json.NewEncoder(w).Encode(domain.HydraLoginRequest{
Challenge: "challenge-123",
Client: domain.HydraClient{
ClientID: "trusted-rp",
ClientID: "headless-login-client",
TokenEndpointAuthMethod: "private_key_jwt",
JWKS: map[string]any{
"keys": []map[string]any{},
@@ -421,7 +421,7 @@ func TestHeadlessPasswordLogin_MissingClientAssertionRejected(t *testing.T) {
app := newHeadlessPasswordLoginTestApp(h)
body, _ := json.Marshal(map[string]string{
"client_id": "trusted-rp",
"client_id": "headless-login-client",
"loginId": "employee001",
"password": "password",
"login_challenge": "challenge-123",
@@ -460,7 +460,7 @@ func TestHeadlessPasswordLogin_InvalidClientAssertionRejected(t *testing.T) {
json.NewEncoder(w).Encode(domain.HydraLoginRequest{
Challenge: "challenge-123",
Client: domain.HydraClient{
ClientID: "trusted-rp",
ClientID: "headless-login-client",
TokenEndpointAuthMethod: "private_key_jwt",
JWKS: jwks,
Metadata: map[string]interface{}{
@@ -491,11 +491,11 @@ func TestHeadlessPasswordLogin_InvalidClientAssertionRejected(t *testing.T) {
clientAssertion := mustHeadlessClientAssertion(
t,
invalidKey,
"trusted-rp",
"headless-login-client",
"http://example.com/api/v1/auth/headless/password/login",
)
body, _ := json.Marshal(map[string]string{
"client_id": "trusted-rp",
"client_id": "headless-login-client",
"client_assertion": clientAssertion,
"loginId": "employee001",
"password": "password",
@@ -524,7 +524,7 @@ func TestHeadlessPasswordLogin_HeadlessDisabledRejected(t *testing.T) {
json.NewEncoder(w).Encode(domain.HydraLoginRequest{
Challenge: "challenge-123",
Client: domain.HydraClient{
ClientID: "trusted-rp",
ClientID: "headless-login-client",
TokenEndpointAuthMethod: "none",
Metadata: map[string]interface{}{
"status": "active",
@@ -549,7 +549,7 @@ func TestHeadlessPasswordLogin_HeadlessDisabledRejected(t *testing.T) {
app := newHeadlessPasswordLoginTestApp(h)
body, _ := json.Marshal(map[string]string{
"client_id": "trusted-rp",
"client_id": "headless-login-client",
"loginId": "employee001",
"password": "password",
"login_challenge": "challenge-123",
@@ -603,7 +603,7 @@ func TestHeadlessPasswordLogin_ClientIDMismatchRejected(t *testing.T) {
app := newHeadlessPasswordLoginTestApp(h)
body, _ := json.Marshal(map[string]string{
"client_id": "trusted-rp",
"client_id": "headless-login-client",
"loginId": "employee001",
"password": "password",
"login_challenge": "challenge-123",

View File

@@ -611,7 +611,7 @@ func TestDevHandler_NoAuditNoAction(t *testing.T) {
})
}
func TestCreateClient_TrustedRPPayloadMapping(t *testing.T) {
func TestCreateClient_HeadlessLoginPayloadMapping(t *testing.T) {
var captured domain.HydraClient
transport := roundTripFunc(func(r *http.Request) (*http.Response, error) {
@@ -653,7 +653,7 @@ func TestCreateClient_TrustedRPPayloadMapping(t *testing.T) {
app.Post("/api/v1/dev/clients", h.CreateClient)
body, _ := json.Marshal(map[string]any{
"name": "Trusted RP App",
"name": "Headless Login App",
"type": "pkce",
"redirectUris": []string{"https://rp.example.com/callback"},
"scopes": []string{"openid", "profile"},
@@ -685,14 +685,14 @@ func TestCreateClient_TrustedRPPayloadMapping(t *testing.T) {
assert.Equal(t, "RS256", captured.Metadata["request_object_signing_alg"])
}
func TestUpdateClient_TrustedRPPayloadMapping(t *testing.T) {
func TestUpdateClient_HeadlessLoginPayloadMapping(t *testing.T) {
var captured domain.HydraClient
transport := roundTripFunc(func(r *http.Request) (*http.Response, error) {
if r.Method == http.MethodGet && r.URL.Path == "/clients/client-trusted" {
if r.Method == http.MethodGet && r.URL.Path == "/clients/client-headless-login" {
return httpJSONAny(r, http.StatusOK, map[string]any{
"client_id": "client-trusted",
"client_name": "Trusted Before",
"client_id": "client-headless-login",
"client_name": "Headless Login Before",
"redirect_uris": []string{"https://before.example.com/callback"},
"grant_types": []string{"authorization_code", "refresh_token"},
"response_types": []string{"code"},
@@ -703,7 +703,7 @@ func TestUpdateClient_TrustedRPPayloadMapping(t *testing.T) {
},
}), nil
}
if r.Method == http.MethodPut && r.URL.Path == "/clients/client-trusted" {
if r.Method == http.MethodPut && r.URL.Path == "/clients/client-headless-login" {
body, err := io.ReadAll(r.Body)
assert.NoError(t, err)
err = json.Unmarshal(body, &captured)
@@ -741,7 +741,7 @@ func TestUpdateClient_TrustedRPPayloadMapping(t *testing.T) {
app.Put("/api/v1/dev/clients/:id", h.UpdateClient)
body, _ := json.Marshal(map[string]any{
"name": "Trusted After",
"name": "Headless Login After",
"type": "pkce",
"tokenEndpointAuthMethod": "private_key_jwt",
"jwksUri": "https://rp.example.com/.well-known/jwks.json",
@@ -750,7 +750,7 @@ func TestUpdateClient_TrustedRPPayloadMapping(t *testing.T) {
"request_object_signing_alg": "RS256",
},
})
req := httptest.NewRequest(http.MethodPut, "/api/v1/dev/clients/client-trusted", bytes.NewReader(body))
req := httptest.NewRequest(http.MethodPut, "/api/v1/dev/clients/client-headless-login", bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
resp, _ := app.Test(req, -1)