mirror of
https://github.com/coder/coder.git
synced 2025-07-08 11:39:50 +00:00
* feat: Validate Git tokens before consuming them This works the exact same way that the Git credential manager does. It ensures the user token is valid before returning it to the client. It's been manually tested on GitHub, GitLab, and BitBucket. * Fix requested changes
91 lines
3.2 KiB
Go
91 lines
3.2 KiB
Go
package gitauth
|
|
|
|
import (
|
|
"context"
|
|
"net/url"
|
|
"regexp"
|
|
|
|
"golang.org/x/oauth2"
|
|
"golang.org/x/oauth2/github"
|
|
|
|
"github.com/coder/coder/coderd/httpmw"
|
|
"github.com/coder/coder/codersdk"
|
|
)
|
|
|
|
// endpoint contains default SaaS URLs for each Git provider.
|
|
var endpoint = map[codersdk.GitProvider]oauth2.Endpoint{
|
|
codersdk.GitProviderAzureDevops: {
|
|
AuthURL: "https://app.vssps.visualstudio.com/oauth2/authorize",
|
|
TokenURL: "https://app.vssps.visualstudio.com/oauth2/token",
|
|
},
|
|
codersdk.GitProviderBitBucket: {
|
|
AuthURL: "https://bitbucket.org/site/oauth2/authorize",
|
|
TokenURL: "https://bitbucket.org/site/oauth2/access_token",
|
|
},
|
|
codersdk.GitProviderGitLab: {
|
|
AuthURL: "https://gitlab.com/oauth/authorize",
|
|
TokenURL: "https://gitlab.com/oauth/token",
|
|
},
|
|
codersdk.GitProviderGitHub: github.Endpoint,
|
|
}
|
|
|
|
// validateURL contains defaults for each provider.
|
|
var validateURL = map[codersdk.GitProvider]string{
|
|
codersdk.GitProviderGitHub: "https://api.github.com/user",
|
|
codersdk.GitProviderGitLab: "https://gitlab.com/oauth/token/info",
|
|
codersdk.GitProviderBitBucket: "https://api.bitbucket.org/2.0/user",
|
|
}
|
|
|
|
// scope contains defaults for each Git provider.
|
|
var scope = map[codersdk.GitProvider][]string{
|
|
codersdk.GitProviderAzureDevops: {"vso.code_write"},
|
|
codersdk.GitProviderBitBucket: {"account", "repository:write"},
|
|
codersdk.GitProviderGitLab: {"write_repository"},
|
|
codersdk.GitProviderGitHub: {"repo"},
|
|
}
|
|
|
|
// regex provides defaults for each Git provider to
|
|
// match their SaaS host URL. This is configurable by each provider.
|
|
var regex = map[codersdk.GitProvider]*regexp.Regexp{
|
|
codersdk.GitProviderAzureDevops: regexp.MustCompile(`dev\.azure\.com`),
|
|
codersdk.GitProviderBitBucket: regexp.MustCompile(`bitbucket\.org`),
|
|
codersdk.GitProviderGitLab: regexp.MustCompile(`gitlab\.com`),
|
|
codersdk.GitProviderGitHub: regexp.MustCompile(`github\.com`),
|
|
}
|
|
|
|
// newJWTOAuthConfig creates a new OAuth2 config that uses a custom
|
|
// assertion method that works with Azure Devops. See:
|
|
// https://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/oauth?view=azure-devops
|
|
func newJWTOAuthConfig(config *oauth2.Config) httpmw.OAuth2Config {
|
|
return &jwtConfig{config}
|
|
}
|
|
|
|
type jwtConfig struct {
|
|
*oauth2.Config
|
|
}
|
|
|
|
func (c *jwtConfig) AuthCodeURL(state string, opts ...oauth2.AuthCodeOption) string {
|
|
return c.Config.AuthCodeURL(state, append(opts, oauth2.SetAuthURLParam("response_type", "Assertion"))...)
|
|
}
|
|
|
|
func (c *jwtConfig) Exchange(ctx context.Context, code string, opts ...oauth2.AuthCodeOption) (*oauth2.Token, error) {
|
|
v := url.Values{
|
|
"client_assertion_type": {},
|
|
"client_assertion": {c.ClientSecret},
|
|
"assertion": {code},
|
|
"grant_type": {},
|
|
}
|
|
if c.RedirectURL != "" {
|
|
v.Set("redirect_uri", c.RedirectURL)
|
|
}
|
|
return c.Config.Exchange(ctx, code,
|
|
append(opts,
|
|
oauth2.SetAuthURLParam("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"),
|
|
oauth2.SetAuthURLParam("client_assertion", c.ClientSecret),
|
|
oauth2.SetAuthURLParam("assertion", code),
|
|
oauth2.SetAuthURLParam("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"),
|
|
oauth2.SetAuthURLParam("code", ""),
|
|
)...,
|
|
)
|
|
}
|