Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
446 changes: 134 additions & 312 deletions backend/api/auth.go

Large diffs are not rendered by default.

83 changes: 83 additions & 0 deletions backend/api/auth/google.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package auth

import (
"bar/internal/config"
"context"
"encoding/json"
"golang.org/x/oauth2"
)

type googleUser struct {
ID string `json:"id"`
Email string `json:"email"`
Name string `json:"name"`
FirstName string `json:"given_name"`
LastName string `json:"family_name"`
Link string `json:"link"`
Picture string `json:"picture"`
}

type GoogleOAuthProvider struct {
}

var googleOAuth2Config *oauth2.Config

func getGoogleOAuthConfig() *oauth2.Config {
// Don't sync it, we always create the same object
if googleOAuth2Config == nil {
conf := config.GetConfig()
clientId := conf.OauthConfig.GoogleClientID
clientSecret := conf.OauthConfig.GoogleClientSecret
redirectUrl := conf.ApiConfig.BasePath + "/auth/google/callback"
googleOAuth2Config = &oauth2.Config{
ClientID: clientId,
ClientSecret: clientSecret,
RedirectURL: redirectUrl,
Scopes: []string{
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/admin.directory.user.readonly",
},
Endpoint: oauth2.Endpoint{
AuthURL: "https://accounts.google.com/o/oauth2/auth",
TokenURL: "https://oauth2.googleapis.com/token",
},
}
}
return googleOAuth2Config
}

func (p *GoogleOAuthProvider) GetOAuthLink(state string) string {
oAuth2Config := getGoogleOAuthConfig()
domainParameter := oauth2.SetAuthURLParam("hd", "telecomnancy.net")
return oAuth2Config.AuthCodeURL(state, oauth2.AccessTypeOffline, domainParameter)
}

func (p *GoogleOAuthProvider) FetchAccountData(requestContext context.Context, oAuthCode string) (*OAuthAccountData, error) {
oAuth2Config := getGoogleOAuthConfig()
token, err := oAuth2Config.Exchange(requestContext, oAuthCode)
if err != nil {
return nil, err
}

// Get user from Google
client := oAuth2Config.Client(requestContext, token)
resp, err := client.Get("https://www.googleapis.com/oauth2/v2/userinfo")
if err != nil {
return nil, err
}
defer resp.Body.Close()

usr := &googleUser{}
err = json.NewDecoder(resp.Body).Decode(usr)
if err != nil {
return nil, err
}
return &OAuthAccountData{
usr.FirstName,
usr.LastName,
usr.Email,
usr.ID,
usr.Picture,
}, nil
}
65 changes: 65 additions & 0 deletions backend/api/auth/oauth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package auth

import (
"context"
"github.com/google/uuid"
"github.com/labstack/echo/v4"
"github.com/patrickmn/go-cache"
"net/http"
"time"
"errors"
)

type OAuthAccountData struct {
FirstName string
LastName string
EmailAdress string
Id string
PictureLink string
}

var InvalidOAuthStateError = errors.New("Invalid OAuth state")
var BrokenOAuthCallbackError = errors.New("Broken OAuth callback")

type OAuthProvider interface {
GetOAuthLink(state string) string
FetchAccountData(requestContext context.Context, oAuthCode string) (*OAuthAccountData, error)
}

type OAuthCallbackFunction interface {
Callback(*OAuthAccountData, echo.Context) error
}

var connectionCache = cache.New(5*time.Minute, 10*time.Minute)

func InitOAuth(ctx echo.Context, callbackFunction OAuthCallbackFunction) error {
state := uuid.NewString()
// Note that it could lead to excessive memory usage if someone request it too many times
connectionCache.SetDefault(state, callbackFunction)
// TODO Use appropriate OAuth provider
oauthProvider := GoogleOAuthProvider{}
url := oauthProvider.GetOAuthLink(state)
return ctx.Redirect(http.StatusFound, url)
}

func ExecuteOAuthCallback(ctx echo.Context, state string, code string) error {
rawCallbackFunction, found := connectionCache.Get(state)
if !found {
// Ignore all request with invalid state for security reasons
return InvalidOAuthStateError
}
connectionCache.Delete(state)
callbackFunction, ok := rawCallbackFunction.(OAuthCallbackFunction)
if !ok {
// Should not happen. But who knows
return BrokenOAuthCallbackError
}
// TODO Use appropriate OAuth provider
oauthProvider := GoogleOAuthProvider{}
account, err := oauthProvider.FetchAccountData(ctx.Request().Context(), code)
if err != nil {
return err
}
return callbackFunction.Callback(account, ctx)
}

196 changes: 0 additions & 196 deletions backend/api/borneQr.go

This file was deleted.

Loading