provider.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. // Copyright 2024 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package auth0
  5. import (
  6. "context"
  7. "fmt"
  8. "strings"
  9. "golang.org/x/oauth2"
  10. "gogs.io/gogs/internal/auth"
  11. )
  12. // Provider contains configuration of an Auth0 authentication provider.
  13. type Provider struct {
  14. config *Config
  15. }
  16. // NewProvider creates a new Auth0 authentication provider.
  17. func NewProvider(cfg *Config) auth.Provider {
  18. return &Provider{
  19. config: cfg,
  20. }
  21. }
  22. // Authenticate performs OAuth2 authentication against Auth0.
  23. // For Auth0 OAuth, the login parameter should be the authorization code
  24. // and password should be the state parameter for validation.
  25. func (p *Provider) Authenticate(code, state string) (*auth.ExternalAccount, error) {
  26. ctx := context.Background()
  27. // Exchange authorization code for access token
  28. token, err := p.config.ExchangeCode(ctx, code)
  29. if err != nil {
  30. if strings.Contains(err.Error(), "invalid_grant") {
  31. return nil, auth.ErrBadCredentials{Args: map[string]any{"code": code}}
  32. }
  33. return nil, fmt.Errorf("failed to exchange code for token: %w", err)
  34. }
  35. // Get user information from Auth0
  36. userInfo, err := p.config.GetUserInfo(ctx, token)
  37. if err != nil {
  38. return nil, fmt.Errorf("failed to get user info: %w", err)
  39. }
  40. // Extract username from email or sub
  41. username := userInfo.Email
  42. if username == "" {
  43. username = userInfo.Sub
  44. }
  45. // Remove domain from email to create username
  46. if strings.Contains(username, "@") {
  47. username = strings.Split(username, "@")[0]
  48. }
  49. return &auth.ExternalAccount{
  50. Login: username,
  51. Name: username,
  52. FullName: userInfo.Name,
  53. Email: userInfo.Email,
  54. Location: userInfo.Locale,
  55. Website: "",
  56. Admin: false, // Auth0 users are not admins by default
  57. }, nil
  58. }
  59. // Config returns the underlying configuration of the Auth0 provider.
  60. func (p *Provider) Config() any {
  61. return p.config
  62. }
  63. // HasTLS returns true since Auth0 always uses TLS.
  64. func (*Provider) HasTLS() bool {
  65. return true
  66. }
  67. // UseTLS returns true since Auth0 always uses TLS.
  68. func (*Provider) UseTLS() bool {
  69. return true
  70. }
  71. // SkipTLSVerify returns false since Auth0 uses valid certificates.
  72. func (*Provider) SkipTLSVerify() bool {
  73. return false
  74. }
  75. // AuthCodeURL generates the Auth0 authorization URL for OAuth2 flow.
  76. func (p *Provider) AuthCodeURL(state string) string {
  77. return p.config.AuthCodeURL(state)
  78. }
  79. // ExchangeCodeForToken exchanges authorization code for access token.
  80. func (p *Provider) ExchangeCodeForToken(ctx context.Context, code string) (*oauth2.Token, error) {
  81. return p.config.ExchangeCode(ctx, code)
  82. }
  83. // GetUserInfo retrieves user information using access token.
  84. func (p *Provider) GetUserInfo(ctx context.Context, token *oauth2.Token) (*UserInfo, error) {
  85. return p.config.GetUserInfo(ctx, token)
  86. }