Merge pull request #1063 from trheyi/main
Implement global OAuth service and enhance cache management in Signin…
This commit is contained in:
commit
e1220f28b0
2 changed files with 54 additions and 47 deletions
|
|
@ -11,6 +11,9 @@ import (
|
||||||
"github.com/yaoapp/yao/share"
|
"github.com/yaoapp/yao/share"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// OAuth is the global OAuth service
|
||||||
|
var OAuth *Service = nil
|
||||||
|
|
||||||
// Service OAuth service
|
// Service OAuth service
|
||||||
type Service struct {
|
type Service struct {
|
||||||
config *Config
|
config *Config
|
||||||
|
|
@ -147,6 +150,8 @@ func NewService(config *Config) (*Service, error) {
|
||||||
signingCerts: signingCerts,
|
signingCerts: signingCerts,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the global OAuth service
|
||||||
|
OAuth = service
|
||||||
return service, nil
|
return service, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -165,6 +170,16 @@ func (s *Service) GetClientProvider() types.ClientProvider {
|
||||||
return s.clientProvider
|
return s.clientProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCache returns the cache for the service
|
||||||
|
func (s *Service) GetCache() store.Store {
|
||||||
|
return s.cache
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStore returns the store for the service
|
||||||
|
func (s *Service) GetStore() store.Store {
|
||||||
|
return s.store
|
||||||
|
}
|
||||||
|
|
||||||
// setConfigDefaults sets default values for configuration
|
// setConfigDefaults sets default values for configuration
|
||||||
func setConfigDefaults(config *Config) error {
|
func setConfigDefaults(config *Config) error {
|
||||||
// Certificate defaults
|
// Certificate defaults
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/yaoapp/gou/session"
|
"github.com/yaoapp/gou/session"
|
||||||
"github.com/yaoapp/gou/store"
|
|
||||||
"github.com/yaoapp/kun/log"
|
"github.com/yaoapp/kun/log"
|
||||||
|
"github.com/yaoapp/yao/openapi/oauth"
|
||||||
"github.com/yaoapp/yao/openapi/oauth/types"
|
"github.com/yaoapp/yao/openapi/oauth/types"
|
||||||
"github.com/yaoapp/yao/openapi/response"
|
"github.com/yaoapp/yao/openapi/response"
|
||||||
"github.com/yaoapp/yao/openapi/utils"
|
"github.com/yaoapp/yao/openapi/utils"
|
||||||
|
|
@ -193,6 +193,8 @@ func authback(c *gin.Context) {
|
||||||
userInfo, err = provider.GetUserInfo(tokenResponse.AccessToken, tokenResponse.TokenType)
|
userInfo, err = provider.GetUserInfo(tokenResponse.AccessToken, tokenResponse.TokenType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create / Update / User then login (Generate access_token and id_token)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorResp := &response.ErrorResponse{
|
errorResp := &response.ErrorResponse{
|
||||||
Code: response.ErrInvalidRequest.Code,
|
Code: response.ErrInvalidRequest.Code,
|
||||||
|
|
@ -293,8 +295,6 @@ func getOAuthAuthorizationURL(c *gin.Context) {
|
||||||
// Add scopes
|
// Add scopes
|
||||||
if len(provider.Scopes) > 0 {
|
if len(provider.Scopes) > 0 {
|
||||||
params.Add("scope", strings.Join(provider.Scopes, " "))
|
params.Add("scope", strings.Join(provider.Scopes, " "))
|
||||||
} else {
|
|
||||||
params.Add("scope", "openid profile email")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add response_mode if specified (required for Apple with name/email scopes)
|
// Add response_mode if specified (required for Apple with name/email scopes)
|
||||||
|
|
@ -398,30 +398,37 @@ func generateSessionID() string {
|
||||||
return session.ID()
|
return session.ID()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// userInfoKey returns the key for the user info
|
||||||
|
func userInfoKey(providerID, state string) string {
|
||||||
|
return fmt.Sprintf("signin:user_info:%s:%s", providerID, state)
|
||||||
|
}
|
||||||
|
|
||||||
|
// stateKey returns the key for the state
|
||||||
|
func stateKey(providerID string) string {
|
||||||
|
return fmt.Sprintf("signin:state:%s", providerID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// redirectURIKey returns the key for the redirect URI
|
||||||
|
func redirectURIKey(providerID, state string) string {
|
||||||
|
return fmt.Sprintf("signin:redirect_uri:%s:%s", providerID, state)
|
||||||
|
}
|
||||||
|
|
||||||
// saveState saves the state to the session
|
// saveState saves the state to the session
|
||||||
func saveState(providerID, sid, state string) error {
|
func saveState(providerID, sid, state string) error {
|
||||||
return session.Global().ID(sid).SetWithEx(fmt.Sprintf("oauth_state_%s", providerID), state, 20*time.Minute)
|
return session.Global().ID(sid).SetWithEx(stateKey(providerID), state, 20*time.Minute)
|
||||||
}
|
}
|
||||||
|
|
||||||
// saveRedirectURI saves the redirect URI to the session
|
// saveRedirectURI saves the redirect URI to the session
|
||||||
func saveRedirectURI(providerID, state, redirectURI string) error {
|
func saveRedirectURI(providerID, state, redirectURI string) error {
|
||||||
key := fmt.Sprintf("oauth_redirect_uri_%s_%s", providerID, state)
|
key := redirectURIKey(providerID, state)
|
||||||
store, err := store.Get("__yao.oauth.cache")
|
store := oauth.OAuth.GetCache()
|
||||||
if err != nil {
|
return store.Set(key, redirectURI, 20*time.Minute)
|
||||||
return err
|
|
||||||
}
|
|
||||||
store.Set(key, redirectURI, 20*time.Minute)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getRedirectURI gets the redirect URI from the session
|
// getRedirectURI gets the redirect URI from the session
|
||||||
func getRedirectURI(providerID, state string) (string, error) {
|
func getRedirectURI(providerID, state string) (string, error) {
|
||||||
key := fmt.Sprintf("oauth_redirect_uri_%s_%s", providerID, state)
|
key := redirectURIKey(providerID, state)
|
||||||
store, err := store.Get("__yao.oauth.cache")
|
store := oauth.OAuth.GetCache()
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
value, ok := store.Get(key)
|
value, ok := store.Get(key)
|
||||||
if !ok || value == nil {
|
if !ok || value == nil {
|
||||||
return "", fmt.Errorf("redirect URI not found")
|
return "", fmt.Errorf("redirect URI not found")
|
||||||
|
|
@ -430,34 +437,22 @@ func getRedirectURI(providerID, state string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeRedirectURI(providerID, state string) error {
|
func removeRedirectURI(providerID, state string) error {
|
||||||
key := fmt.Sprintf("oauth_redirect_uri_%s_%s", providerID, state)
|
key := redirectURIKey(providerID, state)
|
||||||
store, err := store.Get("__yao.oauth.cache")
|
store := oauth.OAuth.GetCache()
|
||||||
if err != nil {
|
return store.Del(key)
|
||||||
return err
|
|
||||||
}
|
|
||||||
store.Del(key)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// saveUserInfo saves the user info to cache (for form_post mode)
|
// saveUserInfo saves the user info to cache (for form_post mode)
|
||||||
func saveUserInfo(providerID, state, userInfo string) error {
|
func saveUserInfo(providerID, state, userInfo string) error {
|
||||||
key := fmt.Sprintf("oauth_user_info_%s_%s", providerID, state)
|
key := userInfoKey(providerID, state)
|
||||||
store, err := store.Get("__yao.oauth.cache")
|
store := oauth.OAuth.GetCache()
|
||||||
if err != nil {
|
return store.Set(key, userInfo, 20*time.Minute)
|
||||||
return err
|
|
||||||
}
|
|
||||||
store.Set(key, userInfo, 20*time.Minute)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getUserInfo gets the user info from cache
|
// getUserInfo gets the user info from cache
|
||||||
func getUserInfo(providerID, state string) (string, error) {
|
func getUserInfo(providerID, state string) (string, error) {
|
||||||
key := fmt.Sprintf("oauth_user_info_%s_%s", providerID, state)
|
key := userInfoKey(providerID, state)
|
||||||
store, err := store.Get("__yao.oauth.cache")
|
store := oauth.OAuth.GetCache()
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
value, ok := store.Get(key)
|
value, ok := store.Get(key)
|
||||||
if !ok || value == nil {
|
if !ok || value == nil {
|
||||||
return "", fmt.Errorf("user info not found")
|
return "", fmt.Errorf("user info not found")
|
||||||
|
|
@ -467,18 +462,15 @@ func getUserInfo(providerID, state string) (string, error) {
|
||||||
|
|
||||||
// removeUserInfo removes the user info from cache
|
// removeUserInfo removes the user info from cache
|
||||||
func removeUserInfo(providerID, state string) error {
|
func removeUserInfo(providerID, state string) error {
|
||||||
key := fmt.Sprintf("oauth_user_info_%s_%s", providerID, state)
|
key := userInfoKey(providerID, state)
|
||||||
store, err := store.Get("__yao.oauth.cache")
|
store := oauth.OAuth.GetCache()
|
||||||
if err != nil {
|
return store.Del(key)
|
||||||
return err
|
|
||||||
}
|
|
||||||
store.Del(key)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// removeState removes the state from the session
|
||||||
func removeState(providerID, sid string) error {
|
func removeState(providerID, sid string) error {
|
||||||
// Get the state from the session
|
// Get the state from the session
|
||||||
state, err := session.Global().ID(sid).Get(fmt.Sprintf("oauth_state_%s", providerID))
|
state, err := session.Global().ID(sid).Get(stateKey(providerID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -493,12 +485,12 @@ func removeState(providerID, sid string) error {
|
||||||
removeRedirectURI(providerID, stateStr)
|
removeRedirectURI(providerID, stateStr)
|
||||||
removeUserInfo(providerID, stateStr)
|
removeUserInfo(providerID, stateStr)
|
||||||
|
|
||||||
return session.Global().ID(sid).Del(fmt.Sprintf("oauth_state_%s", providerID))
|
return session.Global().ID(sid).Del(stateKey(providerID))
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateState validates the state from the session
|
// validateState validates the state from the session
|
||||||
func validateState(providerID, sid, state string) error {
|
func validateState(providerID, sid, state string) error {
|
||||||
value, err := session.Global().ID(sid).Get(fmt.Sprintf("oauth_state_%s", providerID))
|
value, err := session.Global().ID(sid).Get(stateKey(providerID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue