Add comments to exported methods for providers package
This commit is contained in:
parent
a65ceb2c41
commit
e200bd5c20
@ -11,11 +11,13 @@ import (
|
|||||||
"github.com/pusher/oauth2_proxy/api"
|
"github.com/pusher/oauth2_proxy/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// AzureProvider represents an Azure based Identity Provider
|
||||||
type AzureProvider struct {
|
type AzureProvider struct {
|
||||||
*ProviderData
|
*ProviderData
|
||||||
Tenant string
|
Tenant string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewAzureProvider initiates a new AzureProvider
|
||||||
func NewAzureProvider(p *ProviderData) *AzureProvider {
|
func NewAzureProvider(p *ProviderData) *AzureProvider {
|
||||||
p.ProviderName = "Azure"
|
p.ProviderName = "Azure"
|
||||||
|
|
||||||
@ -40,6 +42,7 @@ func NewAzureProvider(p *ProviderData) *AzureProvider {
|
|||||||
return &AzureProvider{ProviderData: p}
|
return &AzureProvider{ProviderData: p}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Configure defaults the AzureProvider configuration options
|
||||||
func (p *AzureProvider) Configure(tenant string) {
|
func (p *AzureProvider) Configure(tenant string) {
|
||||||
p.Tenant = tenant
|
p.Tenant = tenant
|
||||||
if tenant == "" {
|
if tenant == "" {
|
||||||
@ -84,6 +87,7 @@ func getEmailFromJSON(json *simplejson.Json) (string, error) {
|
|||||||
return email, err
|
return email, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetEmailAddress returns the Account email address
|
||||||
func (p *AzureProvider) GetEmailAddress(s *SessionState) (string, error) {
|
func (p *AzureProvider) GetEmailAddress(s *SessionState) (string, error) {
|
||||||
var email string
|
var email string
|
||||||
var err error
|
var err error
|
||||||
|
@ -9,10 +9,12 @@ import (
|
|||||||
"github.com/pusher/oauth2_proxy/api"
|
"github.com/pusher/oauth2_proxy/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// FacebookProvider represents an Facebook based Identity Provider
|
||||||
type FacebookProvider struct {
|
type FacebookProvider struct {
|
||||||
*ProviderData
|
*ProviderData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewFacebookProvider initiates a new FacebookProvider
|
||||||
func NewFacebookProvider(p *ProviderData) *FacebookProvider {
|
func NewFacebookProvider(p *ProviderData) *FacebookProvider {
|
||||||
p.ProviderName = "Facebook"
|
p.ProviderName = "Facebook"
|
||||||
if p.LoginURL.String() == "" {
|
if p.LoginURL.String() == "" {
|
||||||
@ -51,6 +53,7 @@ func getFacebookHeader(accessToken string) http.Header {
|
|||||||
return header
|
return header
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetEmailAddress returns the Account email address
|
||||||
func (p *FacebookProvider) GetEmailAddress(s *SessionState) (string, error) {
|
func (p *FacebookProvider) GetEmailAddress(s *SessionState) (string, error) {
|
||||||
if s.AccessToken == "" {
|
if s.AccessToken == "" {
|
||||||
return "", errors.New("missing access token")
|
return "", errors.New("missing access token")
|
||||||
@ -75,6 +78,7 @@ func (p *FacebookProvider) GetEmailAddress(s *SessionState) (string, error) {
|
|||||||
return r.Email, nil
|
return r.Email, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidateSessionState validates the AccessToken
|
||||||
func (p *FacebookProvider) ValidateSessionState(s *SessionState) bool {
|
func (p *FacebookProvider) ValidateSessionState(s *SessionState) bool {
|
||||||
return validateToken(p, s.AccessToken, getFacebookHeader(s.AccessToken))
|
return validateToken(p, s.AccessToken, getFacebookHeader(s.AccessToken))
|
||||||
}
|
}
|
||||||
|
@ -12,12 +12,14 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GitHubProvider represents an GitHub based Identity Provider
|
||||||
type GitHubProvider struct {
|
type GitHubProvider struct {
|
||||||
*ProviderData
|
*ProviderData
|
||||||
Org string
|
Org string
|
||||||
Team string
|
Team string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewGitHubProvider initiates a new GitHubProvider
|
||||||
func NewGitHubProvider(p *ProviderData) *GitHubProvider {
|
func NewGitHubProvider(p *ProviderData) *GitHubProvider {
|
||||||
p.ProviderName = "GitHub"
|
p.ProviderName = "GitHub"
|
||||||
if p.LoginURL == nil || p.LoginURL.String() == "" {
|
if p.LoginURL == nil || p.LoginURL.String() == "" {
|
||||||
@ -47,6 +49,8 @@ func NewGitHubProvider(p *ProviderData) *GitHubProvider {
|
|||||||
}
|
}
|
||||||
return &GitHubProvider{ProviderData: p}
|
return &GitHubProvider{ProviderData: p}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetOrgTeam adds GitHub org reading parameters to the OAuth2 scope
|
||||||
func (p *GitHubProvider) SetOrgTeam(org, team string) {
|
func (p *GitHubProvider) SetOrgTeam(org, team string) {
|
||||||
p.Org = org
|
p.Org = org
|
||||||
p.Team = team
|
p.Team = team
|
||||||
@ -194,6 +198,7 @@ func (p *GitHubProvider) hasOrgAndTeam(accessToken string) (bool, error) {
|
|||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetEmailAddress returns the Account email address
|
||||||
func (p *GitHubProvider) GetEmailAddress(s *SessionState) (string, error) {
|
func (p *GitHubProvider) GetEmailAddress(s *SessionState) (string, error) {
|
||||||
|
|
||||||
var emails []struct {
|
var emails []struct {
|
||||||
@ -251,6 +256,7 @@ func (p *GitHubProvider) GetEmailAddress(s *SessionState) (string, error) {
|
|||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetUserName returns the Account user name
|
||||||
func (p *GitHubProvider) GetUserName(s *SessionState) (string, error) {
|
func (p *GitHubProvider) GetUserName(s *SessionState) (string, error) {
|
||||||
var user struct {
|
var user struct {
|
||||||
Login string `json:"login"`
|
Login string `json:"login"`
|
||||||
|
@ -8,10 +8,12 @@ import (
|
|||||||
"github.com/pusher/oauth2_proxy/api"
|
"github.com/pusher/oauth2_proxy/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GitLabProvider represents an GitLab based Identity Provider
|
||||||
type GitLabProvider struct {
|
type GitLabProvider struct {
|
||||||
*ProviderData
|
*ProviderData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewGitLabProvider initiates a new GitLabProvider
|
||||||
func NewGitLabProvider(p *ProviderData) *GitLabProvider {
|
func NewGitLabProvider(p *ProviderData) *GitLabProvider {
|
||||||
p.ProviderName = "GitLab"
|
p.ProviderName = "GitLab"
|
||||||
if p.LoginURL == nil || p.LoginURL.String() == "" {
|
if p.LoginURL == nil || p.LoginURL.String() == "" {
|
||||||
@ -41,6 +43,7 @@ func NewGitLabProvider(p *ProviderData) *GitLabProvider {
|
|||||||
return &GitLabProvider{ProviderData: p}
|
return &GitLabProvider{ProviderData: p}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetEmailAddress returns the Account email address
|
||||||
func (p *GitLabProvider) GetEmailAddress(s *SessionState) (string, error) {
|
func (p *GitLabProvider) GetEmailAddress(s *SessionState) (string, error) {
|
||||||
|
|
||||||
req, err := http.NewRequest("GET",
|
req, err := http.NewRequest("GET",
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"google.golang.org/api/googleapi"
|
"google.golang.org/api/googleapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GoogleProvider represents an Google based Identity Provider
|
||||||
type GoogleProvider struct {
|
type GoogleProvider struct {
|
||||||
*ProviderData
|
*ProviderData
|
||||||
RedeemRefreshURL *url.URL
|
RedeemRefreshURL *url.URL
|
||||||
@ -28,6 +29,7 @@ type GoogleProvider struct {
|
|||||||
GroupValidator func(string) bool
|
GroupValidator func(string) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewGoogleProvider initiates a new GoogleProvider
|
||||||
func NewGoogleProvider(p *ProviderData) *GoogleProvider {
|
func NewGoogleProvider(p *ProviderData) *GoogleProvider {
|
||||||
p.ProviderName = "Google"
|
p.ProviderName = "Google"
|
||||||
if p.LoginURL.String() == "" {
|
if p.LoginURL.String() == "" {
|
||||||
@ -90,6 +92,7 @@ func emailFromIDToken(idToken string) (string, error) {
|
|||||||
return email.Email, nil
|
return email.Email, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Redeem exchanges the OAuth2 authentication token for an ID token
|
||||||
func (p *GoogleProvider) Redeem(redirectURL, code string) (s *SessionState, err error) {
|
func (p *GoogleProvider) Redeem(redirectURL, code string) (s *SessionState, err error) {
|
||||||
if code == "" {
|
if code == "" {
|
||||||
err = errors.New("missing code")
|
err = errors.New("missing code")
|
||||||
@ -249,6 +252,8 @@ func (p *GoogleProvider) ValidateGroup(email string) bool {
|
|||||||
return p.GroupValidator(email)
|
return p.GroupValidator(email)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RefreshSessionIfNeeded checks if the session has expired and uses the
|
||||||
|
// RefreshToken to fetch a new ID token if required
|
||||||
func (p *GoogleProvider) RefreshSessionIfNeeded(s *SessionState) (bool, error) {
|
func (p *GoogleProvider) RefreshSessionIfNeeded(s *SessionState) (bool, error) {
|
||||||
if s == nil || s.ExpiresOn.After(time.Now()) || s.RefreshToken == "" {
|
if s == nil || s.ExpiresOn.After(time.Now()) || s.RefreshToken == "" {
|
||||||
return false, nil
|
return false, nil
|
||||||
|
@ -9,10 +9,12 @@ import (
|
|||||||
"github.com/pusher/oauth2_proxy/api"
|
"github.com/pusher/oauth2_proxy/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// LinkedInProvider represents an LinkedIn based Identity Provider
|
||||||
type LinkedInProvider struct {
|
type LinkedInProvider struct {
|
||||||
*ProviderData
|
*ProviderData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewLinkedInProvider initiates a new LinkedInProvider
|
||||||
func NewLinkedInProvider(p *ProviderData) *LinkedInProvider {
|
func NewLinkedInProvider(p *ProviderData) *LinkedInProvider {
|
||||||
p.ProviderName = "LinkedIn"
|
p.ProviderName = "LinkedIn"
|
||||||
if p.LoginURL.String() == "" {
|
if p.LoginURL.String() == "" {
|
||||||
@ -47,6 +49,7 @@ func getLinkedInHeader(accessToken string) http.Header {
|
|||||||
return header
|
return header
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetEmailAddress returns the Account email address
|
||||||
func (p *LinkedInProvider) GetEmailAddress(s *SessionState) (string, error) {
|
func (p *LinkedInProvider) GetEmailAddress(s *SessionState) (string, error) {
|
||||||
if s.AccessToken == "" {
|
if s.AccessToken == "" {
|
||||||
return "", errors.New("missing access token")
|
return "", errors.New("missing access token")
|
||||||
@ -69,6 +72,7 @@ func (p *LinkedInProvider) GetEmailAddress(s *SessionState) (string, error) {
|
|||||||
return email, nil
|
return email, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidateSessionState validates the AccessToken
|
||||||
func (p *LinkedInProvider) ValidateSessionState(s *SessionState) bool {
|
func (p *LinkedInProvider) ValidateSessionState(s *SessionState) bool {
|
||||||
return validateToken(p, s.AccessToken, getLinkedInHeader(s.AccessToken))
|
return validateToken(p, s.AccessToken, getLinkedInHeader(s.AccessToken))
|
||||||
}
|
}
|
||||||
|
@ -10,17 +10,20 @@ import (
|
|||||||
oidc "github.com/coreos/go-oidc"
|
oidc "github.com/coreos/go-oidc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// OIDCProvider represents an OIDC based Identity Provider
|
||||||
type OIDCProvider struct {
|
type OIDCProvider struct {
|
||||||
*ProviderData
|
*ProviderData
|
||||||
|
|
||||||
Verifier *oidc.IDTokenVerifier
|
Verifier *oidc.IDTokenVerifier
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewOIDCProvider initiates a new OIDCProvider
|
||||||
func NewOIDCProvider(p *ProviderData) *OIDCProvider {
|
func NewOIDCProvider(p *ProviderData) *OIDCProvider {
|
||||||
p.ProviderName = "OpenID Connect"
|
p.ProviderName = "OpenID Connect"
|
||||||
return &OIDCProvider{ProviderData: p}
|
return &OIDCProvider{ProviderData: p}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Redeem exchanges the OAuth2 authentication token for an ID token
|
||||||
func (p *OIDCProvider) Redeem(redirectURL, code string) (s *SessionState, err error) {
|
func (p *OIDCProvider) Redeem(redirectURL, code string) (s *SessionState, err error) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
c := oauth2.Config{
|
c := oauth2.Config{
|
||||||
@ -73,6 +76,11 @@ func (p *OIDCProvider) Redeem(redirectURL, code string) (s *SessionState, err er
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RefreshSessionIfNeeded checks if the session has expired and uses the
|
||||||
|
// RefreshToken to fetch a new ID token if required
|
||||||
|
//
|
||||||
|
// WARNGING: This implementation is broken and does not check with the upstream
|
||||||
|
// OIDC provider before refreshing the session
|
||||||
func (p *OIDCProvider) RefreshSessionIfNeeded(s *SessionState) (bool, error) {
|
func (p *OIDCProvider) RefreshSessionIfNeeded(s *SessionState) (bool, error) {
|
||||||
if s == nil || s.ExpiresOn.After(time.Now()) || s.RefreshToken == "" {
|
if s == nil || s.ExpiresOn.After(time.Now()) || s.RefreshToken == "" {
|
||||||
return false, nil
|
return false, nil
|
||||||
|
@ -4,6 +4,8 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ProviderData contains information required to configure all implementations
|
||||||
|
// of OAuth2 providers
|
||||||
type ProviderData struct {
|
type ProviderData struct {
|
||||||
ProviderName string
|
ProviderName string
|
||||||
ClientID string
|
ClientID string
|
||||||
@ -17,4 +19,5 @@ type ProviderData struct {
|
|||||||
ApprovalPrompt string
|
ApprovalPrompt string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Data returns the ProviderData
|
||||||
func (p *ProviderData) Data() *ProviderData { return p }
|
func (p *ProviderData) Data() *ProviderData { return p }
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/pusher/oauth2_proxy/cookie"
|
"github.com/pusher/oauth2_proxy/cookie"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Redeem provides a default implementation of the OAuth2 token redemption process
|
||||||
func (p *ProviderData) Redeem(redirectURL, code string) (s *SessionState, err error) {
|
func (p *ProviderData) Redeem(redirectURL, code string) (s *SessionState, err error) {
|
||||||
if code == "" {
|
if code == "" {
|
||||||
err = errors.New("missing code")
|
err = errors.New("missing code")
|
||||||
@ -102,6 +103,7 @@ func (p *ProviderData) SessionFromCookie(v string, c *cookie.Cipher) (s *Session
|
|||||||
return DecodeSessionState(v, c)
|
return DecodeSessionState(v, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetEmailAddress returns the Account email address
|
||||||
func (p *ProviderData) GetEmailAddress(s *SessionState) (string, error) {
|
func (p *ProviderData) GetEmailAddress(s *SessionState) (string, error) {
|
||||||
return "", errors.New("not implemented")
|
return "", errors.New("not implemented")
|
||||||
}
|
}
|
||||||
@ -117,6 +119,7 @@ func (p *ProviderData) ValidateGroup(email string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidateSessionState validates the AccessToken
|
||||||
func (p *ProviderData) ValidateSessionState(s *SessionState) bool {
|
func (p *ProviderData) ValidateSessionState(s *SessionState) bool {
|
||||||
return validateToken(p, s.AccessToken, nil)
|
return validateToken(p, s.AccessToken, nil)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"github.com/pusher/oauth2_proxy/cookie"
|
"github.com/pusher/oauth2_proxy/cookie"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Provider represents an upstream identity provider implementation
|
||||||
type Provider interface {
|
type Provider interface {
|
||||||
Data() *ProviderData
|
Data() *ProviderData
|
||||||
GetEmailAddress(*SessionState) (string, error)
|
GetEmailAddress(*SessionState) (string, error)
|
||||||
@ -17,6 +18,7 @@ type Provider interface {
|
|||||||
CookieForSession(*SessionState, *cookie.Cipher) (string, error)
|
CookieForSession(*SessionState, *cookie.Cipher) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New provides a new Provider based on the configured provider string
|
||||||
func New(provider string, p *ProviderData) Provider {
|
func New(provider string, p *ProviderData) Provider {
|
||||||
switch provider {
|
switch provider {
|
||||||
case "linkedin":
|
case "linkedin":
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/pusher/oauth2_proxy/cookie"
|
"github.com/pusher/oauth2_proxy/cookie"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SessionState is used to store information about the currently authenticated user session
|
||||||
type SessionState struct {
|
type SessionState struct {
|
||||||
AccessToken string
|
AccessToken string
|
||||||
ExpiresOn time.Time
|
ExpiresOn time.Time
|
||||||
@ -17,6 +18,7 @@ type SessionState struct {
|
|||||||
User string
|
User string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsExpired checks whether the session has expired
|
||||||
func (s *SessionState) IsExpired() bool {
|
func (s *SessionState) IsExpired() bool {
|
||||||
if !s.ExpiresOn.IsZero() && s.ExpiresOn.Before(time.Now()) {
|
if !s.ExpiresOn.IsZero() && s.ExpiresOn.Before(time.Now()) {
|
||||||
return true
|
return true
|
||||||
@ -24,6 +26,7 @@ func (s *SessionState) IsExpired() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String constructs a summary of the session state
|
||||||
func (s *SessionState) String() string {
|
func (s *SessionState) String() string {
|
||||||
o := fmt.Sprintf("Session{%s", s.accountInfo())
|
o := fmt.Sprintf("Session{%s", s.accountInfo())
|
||||||
if s.AccessToken != "" {
|
if s.AccessToken != "" {
|
||||||
@ -38,6 +41,7 @@ func (s *SessionState) String() string {
|
|||||||
return o + "}"
|
return o + "}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EncodeSessionState returns string representation of the current session
|
||||||
func (s *SessionState) EncodeSessionState(c *cookie.Cipher) (string, error) {
|
func (s *SessionState) EncodeSessionState(c *cookie.Cipher) (string, error) {
|
||||||
if c == nil || s.AccessToken == "" {
|
if c == nil || s.AccessToken == "" {
|
||||||
return s.accountInfo(), nil
|
return s.accountInfo(), nil
|
||||||
@ -49,6 +53,7 @@ func (s *SessionState) accountInfo() string {
|
|||||||
return fmt.Sprintf("email:%s user:%s", s.Email, s.User)
|
return fmt.Sprintf("email:%s user:%s", s.Email, s.User)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EncryptedString encrypts the session state into a cookie string
|
||||||
func (s *SessionState) EncryptedString(c *cookie.Cipher) (string, error) {
|
func (s *SessionState) EncryptedString(c *cookie.Cipher) (string, error) {
|
||||||
var err error
|
var err error
|
||||||
if c == nil {
|
if c == nil {
|
||||||
@ -84,6 +89,7 @@ func decodeSessionStatePlain(v string) (s *SessionState, err error) {
|
|||||||
return &SessionState{User: user, Email: email}, nil
|
return &SessionState{User: user, Email: email}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecodeSessionState decodes the session cookie string into a SessionState
|
||||||
func DecodeSessionState(v string, c *cookie.Cipher) (s *SessionState, err error) {
|
func DecodeSessionState(v string, c *cookie.Cipher) (s *SessionState, err error) {
|
||||||
if c == nil {
|
if c == nil {
|
||||||
return decodeSessionStatePlain(v)
|
return decodeSessionStatePlain(v)
|
||||||
|
Loading…
Reference in New Issue
Block a user