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