1package coordinator
2
3import (
4 "strings"
5)
6
7// oauthFlowPatterns are URL patterns that indicate an OAuth flow is in progress.
8// These appear in authorization URLs and callback redirects.
9var oauthFlowPatterns = []string{
10 // OAuth flow indicators
11 "oauth",
12 "authorize",
13 "authorization",
14 "auth/",
15 "/auth",
16 "login",
17 "signin",
18 "sign-in",
19 // OpenID Connect
20 "oidc",
21 "openid",
22 // Callback/redirect endpoints
23 "callback",
24 "redirect",
25 "/cb",
26}
27
28// oauthCallbackPatterns are URL query parameters that indicate an OAuth callback.
29// These appear when the OAuth provider redirects back to the application.
30var oauthCallbackPatterns = []string{
31 // Success parameters
32 "code=",
33 "access_token=",
34 "id_token=",
35 "token_type=",
36 "refresh_token=",
37 // Error parameters
38 "error=",
39 "error_description=",
40 "error_uri=",
41}
42
43// oauthRequestPatterns are query parameters found in OAuth authorization requests.
44var oauthRequestPatterns = []string{
45 "response_type=",
46 "client_id=",
47 "redirect_uri=",
48 "scope=",
49 "state=",
50 "nonce=",
51}
52
53// IsOAuthURL checks if the URL is related to an OAuth flow.
54// This includes authorization endpoints, login pages, and callback URLs.
55func IsOAuthURL(url string) bool {
56 if url == "" {
57 return false
58 }
59 lower := strings.ToLower(url)
60
61 // Check for OAuth flow patterns in URL path
62 for _, pattern := range oauthFlowPatterns {
63 if strings.Contains(lower, pattern) {
64 return true
65 }
66 }
67
68 // Check for OAuth request parameters
69 for _, pattern := range oauthRequestPatterns {
70 if strings.Contains(lower, pattern) {
71 return true
72 }
73 }
74
75 return false
76}
77
78// IsOAuthCallback checks if the URL is an OAuth callback with response parameters.
79// This indicates the OAuth flow has completed (successfully or with error).
80func IsOAuthCallback(url string) bool {
81 if url == "" {
82 return false
83 }
84 lower := strings.ToLower(url)
85
86 // Must contain callback patterns (code=, access_token=, error=, etc.)
87 for _, pattern := range oauthCallbackPatterns {
88 if strings.Contains(lower, pattern) {
89 return true
90 }
91 }
92
93 return false
94}
95
96// ShouldAutoClose determines if a popup at this URL should auto-close.
97// Returns true for OAuth callbacks that indicate flow completion.
98//
99// This is comprehensive detection that handles:
100// - Success: code=, access_token=, id_token=
101// - Errors: error=, error_description=
102// - Various OAuth providers (Google, GitHub, Auth0, etc.)
103func ShouldAutoClose(url string) bool {
104 // Only auto-close on callback URLs that have OAuth response params
105 return IsOAuthCallback(url)
106}
107
108// IsOAuthSuccess checks if the callback indicates successful authentication.
109func IsOAuthSuccess(url string) bool {
110 if url == "" {
111 return false
112 }
113 lower := strings.ToLower(url)
114
115 // Check for success indicators
116 successPatterns := []string{
117 "code=",
118 "access_token=",
119 "id_token=",
120 }
121
122 for _, pattern := range successPatterns {
123 if strings.Contains(lower, pattern) {
124 // Make sure it's not an error response
125 if !strings.Contains(lower, "error=") {
126 return true
127 }
128 }
129 }
130
131 return false
132}
133
134// IsOAuthError checks if the callback indicates an authentication error.
135func IsOAuthError(url string) bool {
136 if url == "" {
137 return false
138 }
139 lower := strings.ToLower(url)
140 return strings.Contains(lower, "error=")
141}