NewAuthorizationCodeHandler creates a new AuthorizationCodeHandler. It performs validation of the configuration and returns an error if it is invalid. The passed config is consumed by the handler and should not be modified after.
(config *AuthorizationCodeHandlerConfig)
| 123 | // It performs validation of the configuration and returns an error if it is invalid. |
| 124 | // The passed config is consumed by the handler and should not be modified after. |
| 125 | func NewAuthorizationCodeHandler(config *AuthorizationCodeHandlerConfig) (*AuthorizationCodeHandler, error) { |
| 126 | if config == nil { |
| 127 | return nil, errors.New("config must be provided") |
| 128 | } |
| 129 | if config.ClientIDMetadataDocumentConfig == nil && |
| 130 | config.PreregisteredClient == nil && |
| 131 | config.DynamicClientRegistrationConfig == nil { |
| 132 | return nil, errors.New("at least one client registration configuration must be provided") |
| 133 | } |
| 134 | if config.AuthorizationCodeFetcher == nil { |
| 135 | return nil, errors.New("AuthorizationCodeFetcher is required") |
| 136 | } |
| 137 | if config.ClientIDMetadataDocumentConfig != nil && !isNonRootHTTPSURL(config.ClientIDMetadataDocumentConfig.URL) { |
| 138 | return nil, fmt.Errorf("client ID metadata document URL must be a non-root HTTPS URL") |
| 139 | } |
| 140 | if config.PreregisteredClient != nil { |
| 141 | if err := config.PreregisteredClient.Validate(); err != nil { |
| 142 | return nil, fmt.Errorf("invalid PreregisteredClient configuration: %w", err) |
| 143 | } |
| 144 | } |
| 145 | dCfg := config.DynamicClientRegistrationConfig |
| 146 | if dCfg != nil { |
| 147 | if dCfg.Metadata == nil { |
| 148 | return nil, errors.New("dynamic client registration requires non-nil Metadata") |
| 149 | } |
| 150 | if len(dCfg.Metadata.RedirectURIs) == 0 { |
| 151 | return nil, errors.New("Metadata.RedirectURIs is required for dynamic client registration") |
| 152 | } |
| 153 | if config.RedirectURL == "" { |
| 154 | config.RedirectURL = dCfg.Metadata.RedirectURIs[0] |
| 155 | } else if !slices.Contains(dCfg.Metadata.RedirectURIs, config.RedirectURL) { |
| 156 | return nil, fmt.Errorf("RedirectURL %q is not in the list of allowed redirect URIs for dynamic client registration", config.RedirectURL) |
| 157 | } |
| 158 | applicationType := inferApplicationType(dCfg.Metadata.RedirectURIs) |
| 159 | if dCfg.Metadata.ApplicationType == "" { |
| 160 | dCfg.Metadata.ApplicationType = applicationType |
| 161 | } else if dCfg.Metadata.ApplicationType != applicationType { |
| 162 | return nil, fmt.Errorf("application type %q conflicts with the application type inferred from redirect URIs", dCfg.Metadata.ApplicationType) |
| 163 | } |
| 164 | } |
| 165 | if config.RedirectURL == "" { |
| 166 | // If the RedirectURL was supposed to be set by the dynamic client registration, |
| 167 | // it should have been set by now. Otherwise, it is required. |
| 168 | return nil, errors.New("RedirectURL is required") |
| 169 | } |
| 170 | if config.Client == nil { |
| 171 | config.Client = http.DefaultClient |
| 172 | } |
| 173 | return &AuthorizationCodeHandler{config: config}, nil |
| 174 | } |
| 175 | |
| 176 | func isNonRootHTTPSURL(u string) bool { |
| 177 | pu, err := url.Parse(u) |
searching dependent graphs…