Feat: Add oauth2 for twitch (#426)
* fix: * removed fmt.Println * Feat: - Add OAuth for twitch --------- Co-authored-by: lemonScaletech <anand.panigrahi@scaletech.xyz> Co-authored-by: Anand Kumar Panigrahi <70533637+lemonScaletech@users.noreply.github.com>
This commit is contained in:
@@ -23,4 +23,6 @@ const (
|
||||
AuthRecipeMethodTwitter = "twitter"
|
||||
// AuthRecipeMethodMicrosoft is the microsoft auth method
|
||||
AuthRecipeMethodMicrosoft = "microsoft"
|
||||
// AuthRecipeMethodTwitch is the twitch auth method
|
||||
AuthRecipeMethodTwitch = "twitch"
|
||||
)
|
||||
|
@@ -118,6 +118,10 @@ const (
|
||||
EnvKeyMicrosoftActiveDirectoryTenantID = "MICROSOFT_ACTIVE_DIRECTORY_TENANT_ID"
|
||||
// EnvKeyMicrosoftClientSecret key for env variable MICROSOFT_CLIENT_SECRET
|
||||
EnvKeyMicrosoftClientSecret = "MICROSOFT_CLIENT_SECRET"
|
||||
// EnvKeyTwitchClientID key for env variable TWITCH_CLIENT_ID
|
||||
EnvKeyTwitchClientID = "TWITCH_CLIENT_ID"
|
||||
// EnvKeyTwitchClientSecret key for env variable TWITCH_CLIENT_SECRET
|
||||
EnvKeyTwitchClientSecret = "TWITCH_CLIENT_SECRET"
|
||||
// EnvKeyOrganizationName key for env variable ORGANIZATION_NAME
|
||||
EnvKeyOrganizationName = "ORGANIZATION_NAME"
|
||||
// EnvKeyOrganizationLogo key for env variable ORGANIZATION_LOGO
|
||||
|
@@ -139,6 +139,8 @@ type ComplexityRoot struct {
|
||||
SMTPUsername func(childComplexity int) int
|
||||
SenderEmail func(childComplexity int) int
|
||||
SenderName func(childComplexity int) int
|
||||
TwitchClientID func(childComplexity int) int
|
||||
TwitchClientSecret func(childComplexity int) int
|
||||
TwitterClientID func(childComplexity int) int
|
||||
TwitterClientSecret func(childComplexity int) int
|
||||
}
|
||||
@@ -173,6 +175,7 @@ type ComplexityRoot struct {
|
||||
IsMultiFactorAuthEnabled func(childComplexity int) int
|
||||
IsSignUpEnabled func(childComplexity int) int
|
||||
IsStrongPasswordEnabled func(childComplexity int) int
|
||||
IsTwitchLoginEnabled func(childComplexity int) int
|
||||
IsTwitterLoginEnabled func(childComplexity int) int
|
||||
Version func(childComplexity int) int
|
||||
}
|
||||
@@ -992,6 +995,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.Env.SenderName(childComplexity), true
|
||||
|
||||
case "Env.TWITCH_CLIENT_ID":
|
||||
if e.complexity.Env.TwitchClientID == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Env.TwitchClientID(childComplexity), true
|
||||
|
||||
case "Env.TWITCH_CLIENT_SECRET":
|
||||
if e.complexity.Env.TwitchClientSecret == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Env.TwitchClientSecret(childComplexity), true
|
||||
|
||||
case "Env.TWITTER_CLIENT_ID":
|
||||
if e.complexity.Env.TwitterClientID == nil {
|
||||
break
|
||||
@@ -1146,6 +1163,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.Meta.IsStrongPasswordEnabled(childComplexity), true
|
||||
|
||||
case "Meta.is_twitch_login_enabled":
|
||||
if e.complexity.Meta.IsTwitchLoginEnabled == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Meta.IsTwitchLoginEnabled(childComplexity), true
|
||||
|
||||
case "Meta.is_twitter_login_enabled":
|
||||
if e.complexity.Meta.IsTwitterLoginEnabled == nil {
|
||||
break
|
||||
@@ -2324,6 +2348,7 @@ type Meta {
|
||||
is_apple_login_enabled: Boolean!
|
||||
is_twitter_login_enabled: Boolean!
|
||||
is_microsoft_login_enabled: Boolean!
|
||||
is_twitch_login_enabled: Boolean!
|
||||
is_email_verification_enabled: Boolean!
|
||||
is_basic_authentication_enabled: Boolean!
|
||||
is_magic_link_login_enabled: Boolean!
|
||||
@@ -2477,6 +2502,8 @@ type Env {
|
||||
MICROSOFT_CLIENT_ID: String
|
||||
MICROSOFT_CLIENT_SECRET: String
|
||||
MICROSOFT_ACTIVE_DIRECTORY_TENANT_ID: String
|
||||
TWITCH_CLIENT_ID: String
|
||||
TWITCH_CLIENT_SECRET: String
|
||||
ORGANIZATION_NAME: String
|
||||
ORGANIZATION_LOGO: String
|
||||
APP_COOKIE_SECURE: Boolean!
|
||||
@@ -2604,6 +2631,8 @@ input UpdateEnvInput {
|
||||
MICROSOFT_CLIENT_ID: String
|
||||
MICROSOFT_CLIENT_SECRET: String
|
||||
MICROSOFT_ACTIVE_DIRECTORY_TENANT_ID: String
|
||||
TWITCH_CLIENT_ID: String
|
||||
TWITCH_CLIENT_SECRET: String
|
||||
ORGANIZATION_NAME: String
|
||||
ORGANIZATION_LOGO: String
|
||||
DEFAULT_AUTHORIZE_RESPONSE_TYPE: String
|
||||
@@ -6833,6 +6862,88 @@ func (ec *executionContext) fieldContext_Env_MICROSOFT_ACTIVE_DIRECTORY_TENANT_I
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Env_TWITCH_CLIENT_ID(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_Env_TWITCH_CLIENT_ID(ctx, field)
|
||||
if err != nil {
|
||||
return graphql.Null
|
||||
}
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.TwitchClientID, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*string)
|
||||
fc.Result = res
|
||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Env_TWITCH_CLIENT_ID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "Env",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type String does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Env_TWITCH_CLIENT_SECRET(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_Env_TWITCH_CLIENT_SECRET(ctx, field)
|
||||
if err != nil {
|
||||
return graphql.Null
|
||||
}
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.TwitchClientSecret, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*string)
|
||||
fc.Result = res
|
||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Env_TWITCH_CLIENT_SECRET(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "Env",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type String does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Env_ORGANIZATION_NAME(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_Env_ORGANIZATION_NAME(ctx, field)
|
||||
if err != nil {
|
||||
@@ -7954,6 +8065,50 @@ func (ec *executionContext) fieldContext_Meta_is_microsoft_login_enabled(ctx con
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Meta_is_twitch_login_enabled(ctx context.Context, field graphql.CollectedField, obj *model.Meta) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_Meta_is_twitch_login_enabled(ctx, field)
|
||||
if err != nil {
|
||||
return graphql.Null
|
||||
}
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.IsTwitchLoginEnabled, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(bool)
|
||||
fc.Result = res
|
||||
return ec.marshalNBoolean2bool(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Meta_is_twitch_login_enabled(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "Meta",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type Boolean does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Meta_is_email_verification_enabled(ctx context.Context, field graphql.CollectedField, obj *model.Meta) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_Meta_is_email_verification_enabled(ctx, field)
|
||||
if err != nil {
|
||||
@@ -10484,6 +10639,8 @@ func (ec *executionContext) fieldContext_Query_meta(ctx context.Context, field g
|
||||
return ec.fieldContext_Meta_is_twitter_login_enabled(ctx, field)
|
||||
case "is_microsoft_login_enabled":
|
||||
return ec.fieldContext_Meta_is_microsoft_login_enabled(ctx, field)
|
||||
case "is_twitch_login_enabled":
|
||||
return ec.fieldContext_Meta_is_twitch_login_enabled(ctx, field)
|
||||
case "is_email_verification_enabled":
|
||||
return ec.fieldContext_Meta_is_email_verification_enabled(ctx, field)
|
||||
case "is_basic_authentication_enabled":
|
||||
@@ -11208,6 +11365,10 @@ func (ec *executionContext) fieldContext_Query__env(ctx context.Context, field g
|
||||
return ec.fieldContext_Env_MICROSOFT_CLIENT_SECRET(ctx, field)
|
||||
case "MICROSOFT_ACTIVE_DIRECTORY_TENANT_ID":
|
||||
return ec.fieldContext_Env_MICROSOFT_ACTIVE_DIRECTORY_TENANT_ID(ctx, field)
|
||||
case "TWITCH_CLIENT_ID":
|
||||
return ec.fieldContext_Env_TWITCH_CLIENT_ID(ctx, field)
|
||||
case "TWITCH_CLIENT_SECRET":
|
||||
return ec.fieldContext_Env_TWITCH_CLIENT_SECRET(ctx, field)
|
||||
case "ORGANIZATION_NAME":
|
||||
return ec.fieldContext_Env_ORGANIZATION_NAME(ctx, field)
|
||||
case "ORGANIZATION_LOGO":
|
||||
@@ -17715,7 +17876,7 @@ func (ec *executionContext) unmarshalInputUpdateEnvInput(ctx context.Context, ob
|
||||
asMap[k] = v
|
||||
}
|
||||
|
||||
fieldsInOrder := [...]string{"ACCESS_TOKEN_EXPIRY_TIME", "ADMIN_SECRET", "CUSTOM_ACCESS_TOKEN_SCRIPT", "OLD_ADMIN_SECRET", "SMTP_HOST", "SMTP_PORT", "SMTP_USERNAME", "SMTP_PASSWORD", "SMTP_LOCAL_NAME", "SENDER_EMAIL", "SENDER_NAME", "JWT_TYPE", "JWT_SECRET", "JWT_PRIVATE_KEY", "JWT_PUBLIC_KEY", "ALLOWED_ORIGINS", "APP_URL", "RESET_PASSWORD_URL", "APP_COOKIE_SECURE", "ADMIN_COOKIE_SECURE", "DISABLE_EMAIL_VERIFICATION", "DISABLE_BASIC_AUTHENTICATION", "DISABLE_MAGIC_LINK_LOGIN", "DISABLE_LOGIN_PAGE", "DISABLE_SIGN_UP", "DISABLE_REDIS_FOR_ENV", "DISABLE_STRONG_PASSWORD", "DISABLE_MULTI_FACTOR_AUTHENTICATION", "ENFORCE_MULTI_FACTOR_AUTHENTICATION", "ROLES", "PROTECTED_ROLES", "DEFAULT_ROLES", "JWT_ROLE_CLAIM", "GOOGLE_CLIENT_ID", "GOOGLE_CLIENT_SECRET", "GITHUB_CLIENT_ID", "GITHUB_CLIENT_SECRET", "FACEBOOK_CLIENT_ID", "FACEBOOK_CLIENT_SECRET", "LINKEDIN_CLIENT_ID", "LINKEDIN_CLIENT_SECRET", "APPLE_CLIENT_ID", "APPLE_CLIENT_SECRET", "TWITTER_CLIENT_ID", "TWITTER_CLIENT_SECRET", "MICROSOFT_CLIENT_ID", "MICROSOFT_CLIENT_SECRET", "MICROSOFT_ACTIVE_DIRECTORY_TENANT_ID", "ORGANIZATION_NAME", "ORGANIZATION_LOGO", "DEFAULT_AUTHORIZE_RESPONSE_TYPE", "DEFAULT_AUTHORIZE_RESPONSE_MODE", "DISABLE_PLAYGROUND", "DISABLE_MAIL_OTP_LOGIN", "DISABLE_TOTP_LOGIN"}
|
||||
fieldsInOrder := [...]string{"ACCESS_TOKEN_EXPIRY_TIME", "ADMIN_SECRET", "CUSTOM_ACCESS_TOKEN_SCRIPT", "OLD_ADMIN_SECRET", "SMTP_HOST", "SMTP_PORT", "SMTP_USERNAME", "SMTP_PASSWORD", "SMTP_LOCAL_NAME", "SENDER_EMAIL", "SENDER_NAME", "JWT_TYPE", "JWT_SECRET", "JWT_PRIVATE_KEY", "JWT_PUBLIC_KEY", "ALLOWED_ORIGINS", "APP_URL", "RESET_PASSWORD_URL", "APP_COOKIE_SECURE", "ADMIN_COOKIE_SECURE", "DISABLE_EMAIL_VERIFICATION", "DISABLE_BASIC_AUTHENTICATION", "DISABLE_MAGIC_LINK_LOGIN", "DISABLE_LOGIN_PAGE", "DISABLE_SIGN_UP", "DISABLE_REDIS_FOR_ENV", "DISABLE_STRONG_PASSWORD", "DISABLE_MULTI_FACTOR_AUTHENTICATION", "ENFORCE_MULTI_FACTOR_AUTHENTICATION", "ROLES", "PROTECTED_ROLES", "DEFAULT_ROLES", "JWT_ROLE_CLAIM", "GOOGLE_CLIENT_ID", "GOOGLE_CLIENT_SECRET", "GITHUB_CLIENT_ID", "GITHUB_CLIENT_SECRET", "FACEBOOK_CLIENT_ID", "FACEBOOK_CLIENT_SECRET", "LINKEDIN_CLIENT_ID", "LINKEDIN_CLIENT_SECRET", "APPLE_CLIENT_ID", "APPLE_CLIENT_SECRET", "TWITTER_CLIENT_ID", "TWITTER_CLIENT_SECRET", "MICROSOFT_CLIENT_ID", "MICROSOFT_CLIENT_SECRET", "MICROSOFT_ACTIVE_DIRECTORY_TENANT_ID", "TWITCH_CLIENT_ID", "TWITCH_CLIENT_SECRET", "ORGANIZATION_NAME", "ORGANIZATION_LOGO", "DEFAULT_AUTHORIZE_RESPONSE_TYPE", "DEFAULT_AUTHORIZE_RESPONSE_MODE", "DISABLE_PLAYGROUND", "DISABLE_MAIL_OTP_LOGIN", "DISABLE_TOTP_LOGIN"}
|
||||
for _, k := range fieldsInOrder {
|
||||
v, ok := asMap[k]
|
||||
if !ok {
|
||||
@@ -18154,6 +18315,24 @@ func (ec *executionContext) unmarshalInputUpdateEnvInput(ctx context.Context, ob
|
||||
return it, err
|
||||
}
|
||||
it.MicrosoftActiveDirectoryTenantID = data
|
||||
case "TWITCH_CLIENT_ID":
|
||||
var err error
|
||||
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("TWITCH_CLIENT_ID"))
|
||||
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.TwitchClientID = data
|
||||
case "TWITCH_CLIENT_SECRET":
|
||||
var err error
|
||||
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("TWITCH_CLIENT_SECRET"))
|
||||
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.TwitchClientSecret = data
|
||||
case "ORGANIZATION_NAME":
|
||||
var err error
|
||||
|
||||
@@ -19136,6 +19315,10 @@ func (ec *executionContext) _Env(ctx context.Context, sel ast.SelectionSet, obj
|
||||
out.Values[i] = ec._Env_MICROSOFT_CLIENT_SECRET(ctx, field, obj)
|
||||
case "MICROSOFT_ACTIVE_DIRECTORY_TENANT_ID":
|
||||
out.Values[i] = ec._Env_MICROSOFT_ACTIVE_DIRECTORY_TENANT_ID(ctx, field, obj)
|
||||
case "TWITCH_CLIENT_ID":
|
||||
out.Values[i] = ec._Env_TWITCH_CLIENT_ID(ctx, field, obj)
|
||||
case "TWITCH_CLIENT_SECRET":
|
||||
out.Values[i] = ec._Env_TWITCH_CLIENT_SECRET(ctx, field, obj)
|
||||
case "ORGANIZATION_NAME":
|
||||
out.Values[i] = ec._Env_ORGANIZATION_NAME(ctx, field, obj)
|
||||
case "ORGANIZATION_LOGO":
|
||||
@@ -19376,6 +19559,11 @@ func (ec *executionContext) _Meta(ctx context.Context, sel ast.SelectionSet, obj
|
||||
if out.Values[i] == graphql.Null {
|
||||
out.Invalids++
|
||||
}
|
||||
case "is_twitch_login_enabled":
|
||||
out.Values[i] = ec._Meta_is_twitch_login_enabled(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
out.Invalids++
|
||||
}
|
||||
case "is_email_verification_enabled":
|
||||
out.Values[i] = ec._Meta_is_email_verification_enabled(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
|
@@ -119,6 +119,8 @@ type Env struct {
|
||||
MicrosoftClientID *string `json:"MICROSOFT_CLIENT_ID,omitempty"`
|
||||
MicrosoftClientSecret *string `json:"MICROSOFT_CLIENT_SECRET,omitempty"`
|
||||
MicrosoftActiveDirectoryTenantID *string `json:"MICROSOFT_ACTIVE_DIRECTORY_TENANT_ID,omitempty"`
|
||||
TwitchClientID *string `json:"TWITCH_CLIENT_ID,omitempty"`
|
||||
TwitchClientSecret *string `json:"TWITCH_CLIENT_SECRET,omitempty"`
|
||||
OrganizationName *string `json:"ORGANIZATION_NAME,omitempty"`
|
||||
OrganizationLogo *string `json:"ORGANIZATION_LOGO,omitempty"`
|
||||
AppCookieSecure bool `json:"APP_COOKIE_SECURE"`
|
||||
@@ -198,6 +200,7 @@ type Meta struct {
|
||||
IsAppleLoginEnabled bool `json:"is_apple_login_enabled"`
|
||||
IsTwitterLoginEnabled bool `json:"is_twitter_login_enabled"`
|
||||
IsMicrosoftLoginEnabled bool `json:"is_microsoft_login_enabled"`
|
||||
IsTwitchLoginEnabled bool `json:"is_twitch_login_enabled"`
|
||||
IsEmailVerificationEnabled bool `json:"is_email_verification_enabled"`
|
||||
IsBasicAuthenticationEnabled bool `json:"is_basic_authentication_enabled"`
|
||||
IsMagicLinkLoginEnabled bool `json:"is_magic_link_login_enabled"`
|
||||
@@ -383,6 +386,8 @@ type UpdateEnvInput struct {
|
||||
MicrosoftClientID *string `json:"MICROSOFT_CLIENT_ID,omitempty"`
|
||||
MicrosoftClientSecret *string `json:"MICROSOFT_CLIENT_SECRET,omitempty"`
|
||||
MicrosoftActiveDirectoryTenantID *string `json:"MICROSOFT_ACTIVE_DIRECTORY_TENANT_ID,omitempty"`
|
||||
TwitchClientID *string `json:"TWITCH_CLIENT_ID,omitempty"`
|
||||
TwitchClientSecret *string `json:"TWITCH_CLIENT_SECRET,omitempty"`
|
||||
OrganizationName *string `json:"ORGANIZATION_NAME,omitempty"`
|
||||
OrganizationLogo *string `json:"ORGANIZATION_LOGO,omitempty"`
|
||||
DefaultAuthorizeResponseType *string `json:"DEFAULT_AUTHORIZE_RESPONSE_TYPE,omitempty"`
|
||||
|
@@ -22,6 +22,7 @@ type Meta {
|
||||
is_apple_login_enabled: Boolean!
|
||||
is_twitter_login_enabled: Boolean!
|
||||
is_microsoft_login_enabled: Boolean!
|
||||
is_twitch_login_enabled: Boolean!
|
||||
is_email_verification_enabled: Boolean!
|
||||
is_basic_authentication_enabled: Boolean!
|
||||
is_magic_link_login_enabled: Boolean!
|
||||
@@ -175,6 +176,8 @@ type Env {
|
||||
MICROSOFT_CLIENT_ID: String
|
||||
MICROSOFT_CLIENT_SECRET: String
|
||||
MICROSOFT_ACTIVE_DIRECTORY_TENANT_ID: String
|
||||
TWITCH_CLIENT_ID: String
|
||||
TWITCH_CLIENT_SECRET: String
|
||||
ORGANIZATION_NAME: String
|
||||
ORGANIZATION_LOGO: String
|
||||
APP_COOKIE_SECURE: Boolean!
|
||||
@@ -302,6 +305,8 @@ input UpdateEnvInput {
|
||||
MICROSOFT_CLIENT_ID: String
|
||||
MICROSOFT_CLIENT_SECRET: String
|
||||
MICROSOFT_ACTIVE_DIRECTORY_TENANT_ID: String
|
||||
TWITCH_CLIENT_ID: String
|
||||
TWITCH_CLIENT_SECRET: String
|
||||
ORGANIZATION_NAME: String
|
||||
ORGANIZATION_LOGO: String
|
||||
DEFAULT_AUTHORIZE_RESPONSE_TYPE: String
|
||||
|
@@ -11,11 +11,13 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/coreos/go-oidc/v3/oidc"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/cookie"
|
||||
@@ -75,6 +77,8 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
||||
user, err = processTwitterUserInfo(ctx, oauthCode, sessionState)
|
||||
case constants.AuthRecipeMethodMicrosoft:
|
||||
user, err = processMicrosoftUserInfo(ctx, oauthCode)
|
||||
case constants.AuthRecipeMethodTwitch:
|
||||
user, err = processTwitchUserInfo(ctx, oauthCode)
|
||||
default:
|
||||
log.Info("Invalid oauth provider")
|
||||
err = fmt.Errorf(`invalid oauth provider`)
|
||||
@@ -703,3 +707,41 @@ func processMicrosoftUserInfo(ctx context.Context, code string) (*models.User, e
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// process twitch user information
|
||||
func processTwitchUserInfo(ctx context.Context, code string) (*models.User, error) {
|
||||
oauth2Token, err := oauth.OAuthProviders.TwitchConfig.Exchange(ctx, code)
|
||||
if err != nil {
|
||||
log.Debug("Failed to exchange code for token: ", err)
|
||||
return nil, fmt.Errorf("invalid twitch exchange code: %s", err.Error())
|
||||
}
|
||||
|
||||
// Extract the ID Token from OAuth2 token.
|
||||
rawIDToken, ok := oauth2Token.Extra("id_token").(string)
|
||||
if !ok {
|
||||
log.Debug("Failed to extract ID Token from OAuth2 token")
|
||||
return nil, fmt.Errorf("unable to extract id_token")
|
||||
}
|
||||
|
||||
// we need to skip issuer check because for common tenant it will return internal issuer which does not match
|
||||
verifier := oauth.OIDCProviders.TwitchOIDC.Verifier(&oidc.Config{
|
||||
ClientID: oauth.OAuthProviders.TwitchConfig.ClientID,
|
||||
SkipIssuerCheck: true,
|
||||
})
|
||||
|
||||
// Parse and verify ID Token payload.
|
||||
idToken, err := verifier.Verify(ctx, rawIDToken)
|
||||
if err != nil {
|
||||
log.Debug("Failed to verify ID Token: ", err)
|
||||
return nil, fmt.Errorf("unable to verify id_token: %s", err.Error())
|
||||
}
|
||||
|
||||
user := &models.User{}
|
||||
if err := idToken.Claims(&user); err != nil {
|
||||
log.Debug("Failed to parse ID Token claims: ", err)
|
||||
return nil, fmt.Errorf("unable to extract claims")
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
|
@@ -4,10 +4,12 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||
"github.com/authorizerdev/authorizer/server/oauth"
|
||||
@@ -227,6 +229,24 @@ func OAuthLoginHandler() gin.HandlerFunc {
|
||||
oauth.OAuthProviders.MicrosoftConfig.RedirectURL = hostname + "/oauth_callback/" + constants.AuthRecipeMethodMicrosoft
|
||||
url := oauth.OAuthProviders.MicrosoftConfig.AuthCodeURL(oauthStateString)
|
||||
c.Redirect(http.StatusTemporaryRedirect, url)
|
||||
case constants.AuthRecipeMethodTwitch:
|
||||
if oauth.OAuthProviders.TwitchConfig == nil {
|
||||
log.Debug("Twitch OAuth provider is not configured")
|
||||
isProviderConfigured = false
|
||||
break
|
||||
}
|
||||
err := memorystore.Provider.SetState(oauthStateString, constants.AuthRecipeMethodTwitch)
|
||||
if err != nil {
|
||||
log.Debug("Error setting state: ", err)
|
||||
c.JSON(500, gin.H{
|
||||
"error": "internal server error",
|
||||
})
|
||||
return
|
||||
}
|
||||
// during the init of OAuthProvider authorizer url might be empty
|
||||
oauth.OAuthProviders.TwitchConfig.RedirectURL = hostname + "/oauth_callback/" + constants.AuthRecipeMethodTwitch
|
||||
url := oauth.OAuthProviders.TwitchConfig.AuthCodeURL(oauthStateString)
|
||||
c.Redirect(http.StatusTemporaryRedirect, url)
|
||||
default:
|
||||
log.Debug("Invalid oauth provider: ", provider)
|
||||
c.JSON(422, gin.H{
|
||||
|
@@ -4,13 +4,16 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/coreos/go-oidc/v3/oidc"
|
||||
"golang.org/x/oauth2"
|
||||
"google.golang.org/appengine/log"
|
||||
|
||||
facebookOAuth2 "golang.org/x/oauth2/facebook"
|
||||
githubOAuth2 "golang.org/x/oauth2/github"
|
||||
linkedInOAuth2 "golang.org/x/oauth2/linkedin"
|
||||
microsoftOAuth2 "golang.org/x/oauth2/microsoft"
|
||||
"google.golang.org/appengine/log"
|
||||
twitchOAuth2 "golang.org/x/oauth2/twitch"
|
||||
|
||||
"github.com/coreos/go-oidc/v3/oidc"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||
@@ -29,12 +32,14 @@ type OAuthProvider struct {
|
||||
AppleConfig *oauth2.Config
|
||||
TwitterConfig *oauth2.Config
|
||||
MicrosoftConfig *oauth2.Config
|
||||
TwitchConfig *oauth2.Config
|
||||
}
|
||||
|
||||
// OIDCProviders is a struct that contains reference all the OpenID providers
|
||||
type OIDCProvider struct {
|
||||
GoogleOIDC *oidc.Provider
|
||||
MicrosoftOIDC *oidc.Provider
|
||||
TwitchOIDC *oidc.Provider
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -198,5 +203,31 @@ func InitOAuth() error {
|
||||
}
|
||||
}
|
||||
|
||||
twitchClientID, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyTwitchClientID)
|
||||
if err != nil {
|
||||
twitchClientID = ""
|
||||
}
|
||||
twitchClientSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyTwitchClientSecret)
|
||||
if err != nil {
|
||||
twitchClientSecret = ""
|
||||
}
|
||||
|
||||
if twitchClientID != "" && twitchClientSecret != "" {
|
||||
p, err := oidc.NewProvider(ctx, "https://id.twitch.tv/oauth2")
|
||||
if err != nil {
|
||||
log.Debugf(ctx, "Error while creating OIDC provider for Twitch: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
OIDCProviders.TwitchOIDC = p
|
||||
OAuthProviders.TwitchConfig = &oauth2.Config{
|
||||
ClientID: twitchClientID,
|
||||
ClientSecret: twitchClientSecret,
|
||||
RedirectURL: "/oauth_callback/twitch",
|
||||
Endpoint: twitchOAuth2.Endpoint,
|
||||
Scopes: []string{oidc.ScopeOpenID},
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@@ -164,7 +164,12 @@ func EnvResolver(ctx context.Context) (*model.Env, error) {
|
||||
if val, ok := store[constants.EnvKeyMicrosoftActiveDirectoryTenantID]; ok {
|
||||
res.MicrosoftActiveDirectoryTenantID = refs.NewStringRef(val.(string))
|
||||
}
|
||||
|
||||
if val, ok := store[constants.EnvKeyTwitchClientID]; ok {
|
||||
res.TwitchClientID = refs.NewStringRef(val.(string))
|
||||
}
|
||||
if val, ok := store[constants.EnvKeyTwitchClientSecret]; ok {
|
||||
res.TwitchClientSecret = refs.NewStringRef(val.(string))
|
||||
}
|
||||
if val, ok := store[constants.EnvKeyOrganizationName]; ok {
|
||||
res.OrganizationName = refs.NewStringRef(val.(string))
|
||||
}
|
||||
|
@@ -34,6 +34,7 @@ func clearSessionIfRequired(currentData, updatedData map[string]interface{}) {
|
||||
isCurrentLinkedInLoginEnabled := currentData[constants.EnvKeyLinkedInClientID] != nil && currentData[constants.EnvKeyLinkedInClientSecret] != nil && currentData[constants.EnvKeyLinkedInClientID].(string) != "" && currentData[constants.EnvKeyLinkedInClientSecret].(string) != ""
|
||||
isCurrentTwitterLoginEnabled := currentData[constants.EnvKeyTwitterClientID] != nil && currentData[constants.EnvKeyTwitterClientSecret] != nil && currentData[constants.EnvKeyTwitterClientID].(string) != "" && currentData[constants.EnvKeyTwitterClientSecret].(string) != ""
|
||||
isCurrentMicrosoftLoginEnabled := currentData[constants.EnvKeyMicrosoftClientID] != nil && currentData[constants.EnvKeyMicrosoftClientSecret] != nil && currentData[constants.EnvKeyMicrosoftClientID].(string) != "" && currentData[constants.EnvKeyMicrosoftClientSecret].(string) != ""
|
||||
isCurrentTwitchLoginEnabled := currentData[constants.EnvKeyTwitchClientID] != nil && currentData[constants.EnvKeyTwitchClientSecret] != nil && currentData[constants.EnvKeyTwitchClientID].(string) != "" && currentData[constants.EnvKeyTwitchClientSecret].(string) != ""
|
||||
|
||||
isUpdatedBasicAuthEnabled := !updatedData[constants.EnvKeyDisableBasicAuthentication].(bool)
|
||||
isUpdatedMobileBasicAuthEnabled := !updatedData[constants.EnvKeyDisableMobileBasicAuthentication].(bool)
|
||||
@@ -45,6 +46,7 @@ func clearSessionIfRequired(currentData, updatedData map[string]interface{}) {
|
||||
isUpdatedLinkedInLoginEnabled := updatedData[constants.EnvKeyLinkedInClientID] != nil && updatedData[constants.EnvKeyLinkedInClientSecret] != nil && updatedData[constants.EnvKeyLinkedInClientID].(string) != "" && updatedData[constants.EnvKeyLinkedInClientSecret].(string) != ""
|
||||
isUpdatedTwitterLoginEnabled := updatedData[constants.EnvKeyTwitterClientID] != nil && updatedData[constants.EnvKeyTwitterClientSecret] != nil && updatedData[constants.EnvKeyTwitterClientID].(string) != "" && updatedData[constants.EnvKeyTwitterClientSecret].(string) != ""
|
||||
isUpdatedMicrosoftLoginEnabled := updatedData[constants.EnvKeyMicrosoftClientID] != nil && updatedData[constants.EnvKeyMicrosoftClientSecret] != nil && updatedData[constants.EnvKeyMicrosoftClientID].(string) != "" && updatedData[constants.EnvKeyMicrosoftClientSecret].(string) != ""
|
||||
isUpdatedTwitchLoginEnabled := updatedData[constants.EnvKeyTwitchClientID] != nil && updatedData[constants.EnvKeyTwitchClientSecret] != nil && updatedData[constants.EnvKeyTwitchClientID].(string) != "" && updatedData[constants.EnvKeyTwitchClientSecret].(string) != ""
|
||||
|
||||
if isCurrentBasicAuthEnabled && !isUpdatedBasicAuthEnabled {
|
||||
memorystore.Provider.DeleteSessionForNamespace(constants.AuthRecipeMethodBasicAuth)
|
||||
@@ -85,6 +87,10 @@ func clearSessionIfRequired(currentData, updatedData map[string]interface{}) {
|
||||
if isCurrentMicrosoftLoginEnabled && !isUpdatedMicrosoftLoginEnabled {
|
||||
memorystore.Provider.DeleteSessionForNamespace(constants.AuthRecipeMethodMicrosoft)
|
||||
}
|
||||
|
||||
if isCurrentTwitchLoginEnabled && !isUpdatedTwitchLoginEnabled {
|
||||
memorystore.Provider.DeleteSessionForNamespace(constants.AuthRecipeMethodTwitch)
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateEnvResolver is a resolver for update config mutation
|
||||
|
Reference in New Issue
Block a user