go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/sdk/oauth/config.go (about)

     1  /*
     2  
     3  Copyright (c) 2023 - Present. Will Charczuk. All rights reserved.
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository.
     5  
     6  */
     7  
     8  package oauth
     9  
    10  import (
    11  	"context"
    12  	"crypto/rand"
    13  	"encoding/hex"
    14  
    15  	"go.charczuk.com/sdk/configutil"
    16  )
    17  
    18  // Config is the config options.
    19  type Config struct {
    20  	// ClientID is part of the oauth credential pair.
    21  	ClientID string `json:"clientID,omitempty" yaml:"clientID,omitempty"`
    22  	// ClientSecret is part of the oauth credential pair.
    23  	ClientSecret string `json:"clientSecret,omitempty" yaml:"clientSecret,omitempty"`
    24  	// Secret is an encryption key used to verify oauth state.
    25  	Secret string `json:"secret,omitempty" yaml:"secret,omitempty"`
    26  	// RedirectURL is the oauth return url.
    27  	RedirectURL string `json:"redirectURL,omitempty" yaml:"redirectURL,omitempty"`
    28  	// HostedDomain is a specific domain we want to filter identities to.
    29  	HostedDomain string `json:"hostedDomain,omitempty" yaml:"hostedDomain,omitempty"`
    30  	// AllowedDomains is a strict list of hosted domains to allow authenticated users from.
    31  	// If it is unset or empty, it will allow users from *any* hosted domain.
    32  	AllowedDomains []string `json:"allowedDomains,omitempty" yaml:"allowedDomains,omitempty"`
    33  	// Scopes are oauth scopes to request.
    34  	Scopes []string `json:"scopes,omitempty" yaml:"scopes,omitempty"`
    35  }
    36  
    37  // IsZero returns if the config is set or not.
    38  func (c Config) IsZero() bool {
    39  	return len(c.ClientID) == 0 || len(c.ClientSecret) == 0
    40  }
    41  
    42  // Resolve adds extra steps to perform during `configutil.Read(...)`.
    43  func (c *Config) Resolve(ctx context.Context) error {
    44  	return configutil.Resolve(ctx,
    45  		configutil.Set(&c.ClientID, configutil.Env[string]("OAUTH_CLIENT_ID"), configutil.Lazy(&c.ClientID)),
    46  		configutil.Set(&c.ClientSecret, configutil.Env[string]("OAUTH_CLIENT_SECRET"), configutil.Lazy(&c.ClientSecret)),
    47  		configutil.Set(&c.Secret, configutil.Env[string]("OAUTH_SECRET"), configutil.Lazy(&c.Secret), c.GenerateSecret),
    48  		configutil.Set(&c.RedirectURL, configutil.Env[string]("OAUTH_REDIRECT_URL"), configutil.Lazy(&c.RedirectURL)),
    49  		configutil.Set(&c.HostedDomain, configutil.Env[string]("OAUTH_HOSTED_DOMAIN"), configutil.Lazy(&c.HostedDomain)),
    50  	)
    51  }
    52  
    53  // ScopesOrDefault returns the scopes or a default set.
    54  func (c Config) ScopesOrDefault() []string {
    55  	if len(c.Scopes) > 0 {
    56  		return c.Scopes
    57  	}
    58  	return DefaultScopes
    59  }
    60  
    61  // GenerateSecret generates a secret.
    62  func (c Config) GenerateSecret(_ context.Context) (*string, error) {
    63  	buf := make([]byte, 64)
    64  	_, err := rand.Read(buf)
    65  	if err != nil {
    66  		return nil, err
    67  	}
    68  	value := hex.EncodeToString(buf)
    69  	return &value, nil
    70  }
    71  
    72  // DecodeSecret decodes the secret if set from hex encoding.
    73  func (c Config) DecodeSecret() ([]byte, error) {
    74  	if c.Secret != "" {
    75  		decoded, err := hex.DecodeString(c.Secret)
    76  		if err != nil {
    77  			return nil, err
    78  		}
    79  		return decoded, nil
    80  	}
    81  	return nil, nil
    82  }