make oauth as a service

This commit is contained in:
Kenta420-Poom 2023-09-21 14:21:14 +07:00
parent da4110a47b
commit dbc741ccf6
5 changed files with 160 additions and 97 deletions

View file

@ -0,0 +1,105 @@
package oauth
import (
"context"
"encoding/json"
"errors"
"os"
"recipe-manager/config"
"recipe-manager/models"
"golang.org/x/oauth2"
)
type OAuthService interface {
AuthURL(state string, stateMap map[string]string) string
GetState(state string) (map[string]string, bool)
RemoveState(state string)
Exchange(ctx context.Context, code string) (*oauth2.Token, error)
GetUserInfo(ctx context.Context, token *oauth2.Token) (*models.User, error)
RefreshToken(ctx context.Context, token *oauth2.Token) (*oauth2.Token, error)
}
type oauthService struct {
cfg *config.ServerConfig
gConfig *oauth2.Config
nonce map[string]map[string]string
}
func NewOAuthService(cfg *config.ServerConfig) OAuthService {
file, err := os.Open("client_secret.json")
if err != nil {
panic(err)
}
defer file.Close()
var clientSecret map[string]interface{}
json.NewDecoder(file).Decode(&clientSecret)
return &oauthService{
cfg: cfg,
gConfig: &oauth2.Config{
ClientID: clientSecret["web"].(map[string]interface{})["client_id"].(string),
ClientSecret: clientSecret["web"].(map[string]interface{})["client_secret"].(string),
RedirectURL: cfg.ServerDomain + "/auth/google/callback",
Scopes: []string{"https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile"},
Endpoint: oauth2.Endpoint{
AuthURL: clientSecret["web"].(map[string]interface{})["auth_uri"].(string),
TokenURL: clientSecret["web"].(map[string]interface{})["token_uri"].(string),
},
},
nonce: make(map[string]map[string]string),
}
}
func (o *oauthService) AuthURL(state string, stateMap map[string]string) string {
if stateMap != nil {
o.nonce[state] = stateMap
} else {
o.nonce[state] = make(map[string]string)
}
return o.gConfig.AuthCodeURL(state, oauth2.SetAuthURLParam("hd", "forth.co.th"), oauth2.SetAuthURLParam("include_granted_scopes", "true"), oauth2.AccessTypeOffline)
}
func (o *oauthService) GetState(state string) (map[string]string, bool) {
val, ok := o.nonce[state]
return val, ok
}
func (o *oauthService) RemoveState(state string) {
delete(o.nonce, state)
}
func (o *oauthService) Exchange(ctx context.Context, code string) (*oauth2.Token, error) {
return o.gConfig.Exchange(ctx, code)
}
func (o *oauthService) GetUserInfo(ctx context.Context, token *oauth2.Token) (*models.User, error) {
client := o.gConfig.Client(ctx, token)
resp, err := client.Get("https://www.googleapis.com/oauth2/v3/userinfo")
if err != nil {
return nil, err
}
defer resp.Body.Close()
var userInfo map[string]interface{}
json.NewDecoder(resp.Body).Decode(&userInfo)
if userInfo["error"] != nil {
return nil, errors.New("Error getting user info")
}
return &models.User{
Name: userInfo["name"].(string),
Email: userInfo["email"].(string),
Picture: userInfo["picture"].(string),
}, nil
}
func (o *oauthService) RefreshToken(ctx context.Context, token *oauth2.Token) (*oauth2.Token, error) {
return o.gConfig.TokenSource(ctx, token).Token()
}