-
Notifications
You must be signed in to change notification settings - Fork 19
Expand file tree
/
Copy pathprovider.go
More file actions
147 lines (118 loc) · 3.72 KB
/
provider.go
File metadata and controls
147 lines (118 loc) · 3.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright 2025 Copyright AGNTCY Contributors (https://github.com/agntcy)
// SPDX-License-Identifier: Apache-2.0
package oidc
import (
"context"
"errors"
"fmt"
"net/http"
"net/url"
"strings"
"github.com/agntcy/identity/internal/pkg/httputil"
"github.com/agntcy/identity/internal/pkg/log"
)
func (p *parser) detectProviderName(
ctx context.Context,
provider *providerMetadata,
) (ProviderName, error) {
_, headers, err := httputil.Get(ctx, provider.JWKSURL, nil)
if err != nil {
return UnknownProviderName, err
}
providerUrl, _ := url.Parse(provider.JWKSURL)
switch {
case isOry(headers, providerUrl.Host):
return OryProviderName, nil
case isOkta(headers, providerUrl.Host):
return OktaProviderName, nil
case isDuo(headers, providerUrl.Host):
return DuoProviderName, nil
case isPing(headers, providerUrl.Host):
return PingProviderName, nil
case isEntra(headers, providerUrl.Host):
return EntraProviderName, nil
default:
return IdpProviderName, nil
}
}
func isOry(headers http.Header, host string) bool {
return headers != nil &&
(headers.Get("Ory-Network-Region") != "" || strings.HasSuffix(host, "oryapis.com"))
}
func isOkta(headers http.Header, _ string) bool {
return headers != nil && headers.Get("X-Okta-Request-Id") != ""
}
func isDuo(headers http.Header, host string) bool {
return headers != nil &&
(strings.HasPrefix(strings.ToLower(headers.Get("Server")), "duo") ||
strings.HasPrefix(host, "duosecurity.com"))
}
func isPing(_ http.Header, host string) bool {
return strings.HasSuffix(host, "pingone.com") ||
strings.HasSuffix(host, "pingone.eu") ||
strings.HasSuffix(host, "pingone.com.au") ||
strings.HasSuffix(host, "pingone.ca")
}
func isEntra(_ http.Header, host string) bool {
return strings.HasSuffix(host, "microsoftonline.com")
}
func getProviderMetadata(ctx context.Context, issuer string) (*providerMetadata, error) {
metadata, oidcErr := getOidcProviderMetadata(ctx, issuer)
if oidcErr == nil {
return metadata, nil
}
metadata, oauthErr := getOAuthProviderMetadata(ctx, issuer)
if oauthErr == nil {
return metadata, nil
}
return nil, errors.Join(oidcErr, oauthErr)
}
func getOidcProviderMetadata(ctx context.Context, issuer string) (*providerMetadata, error) {
oidcWellKnownURL := getOidcWellKnownURL(issuer)
log.Debug("Getting metadata from issuer:", issuer, " with URL:", oidcWellKnownURL)
metadata, err := getAuthSrvMetadata(ctx, oidcWellKnownURL)
if err != nil {
return nil, err
}
return metadata, err
}
func getOAuthProviderMetadata(ctx context.Context, issuer string) (*providerMetadata, error) {
oauthWellKnownURL := getOAuthWellKnownURL(issuer)
metadata, err := getAuthSrvMetadata(ctx, oauthWellKnownURL)
if err != nil {
return nil, err
}
return metadata, err
}
func getAuthSrvMetadata(ctx context.Context, wellKnownURL string) (*providerMetadata, error) {
var metadata providerMetadata
log.Debug("Getting metadata for the autorization server:", wellKnownURL)
err := httputil.GetJSON(ctx, wellKnownURL, &metadata)
if err != nil {
return nil, fmt.Errorf("failed to get metadata from issuer: %w", err)
}
log.Debug("Got metadata from issuer:", metadata)
return &metadata, nil
}
func getOidcWellKnownURL(issuer string) string {
return issuer + "/.well-known/openid-configuration"
}
func getOAuthWellKnownURL(issuer string) string {
// Get host and path from the issuer URL
u, err := url.Parse(issuer)
if err != nil {
log.Error("Failed to parse issuer URL:", err)
return ""
}
// Construct the well-known URL for OAuth
result, err := url.JoinPath(
fmt.Sprintf("%s://%s", u.Scheme, u.Host),
".well-known/oauth-authorization-server",
u.Path,
)
if err != nil {
log.Error("Failed to construct oauth well-know URL:", err)
return ""
}
return result
}