Skip to content

Commit

Permalink
implement oauth2 getLoginURL [#523]
Browse files Browse the repository at this point in the history
  • Loading branch information
roberlander2 committed Aug 16, 2022
1 parent 2d420be commit eb9f30b
Showing 1 changed file with 95 additions and 7 deletions.
102 changes: 95 additions & 7 deletions core/auth/auth_type_oauth2.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,25 @@ package auth

import (
"core-building-block/core/model"
"core-building-block/utils"
"encoding/json"
"net/url"
"strconv"

"github.com/rokwire/logging-library-go/errors"
"github.com/rokwire/logging-library-go/logs"
"github.com/rokwire/logging-library-go/logutils"
"gopkg.in/go-playground/validator.v9"
)

const (
//AuthTypeOAuth2 oauth2 auth type
AuthTypeOAuth2 string = "oauth2"

typeOAuth2AuthConfig logutils.MessageDataType = "oauth2 auth config"
typeOAuth2Token logutils.MessageDataType = "oauth2 token"
typeOAuth2AuthConfig logutils.MessageDataType = "oauth2 auth config"
typeOAuth2LoginParams logutils.MessageDataType = "oauth2 login params"
typeOAuth2RefreshParams logutils.MessageDataType = "oauth2 refresh params"
typeOAuth2Token logutils.MessageDataType = "oauth2 token"
)

// OAuth2 implementation of authType
Expand All @@ -43,8 +50,9 @@ type oauth2AuthConfig struct {
UserInfoURL string `json:"userinfo_url"`
Scopes string `json:"scopes"`
AllowSignUp bool `json:"allow_signup"`
UseState bool `json:"use_state"`
ClientID string `json:"client_id" validate:"required"`
ClientSecret string `json:"client_secret"`
ClientSecret string `json:"client_secret" validate:"required"`
}

type oauth2Token struct {
Expand All @@ -53,21 +61,101 @@ type oauth2Token struct {
TokenType string `json:"token_type" validate:"required"`
}

type oauth2RefreshParams struct {
RefreshToken string `json:"refresh_token" bson:"refresh_token" validate:"required"`
}

func (a *oauth2AuthImpl) externalLogin(authType model.AuthType, appType model.ApplicationType, appOrg model.ApplicationOrganization, creds string, params string, l *logs.Log) (*model.ExternalSystemUser, map[string]interface{}, error) {
return nil, nil, errors.New(logutils.Unimplemented)
}

// refresh must be implemented for OIDC auth
func (a *oauth2AuthImpl) refresh(params map[string]interface{}, authType model.AuthType, appType model.ApplicationType, appOrg model.ApplicationOrganization, l *logs.Log) (*model.ExternalSystemUser, map[string]interface{}, error) {
return nil, nil, errors.New(logutils.Unimplemented)
}

func (a *oauth2AuthImpl) getLoginURL(authType model.AuthType, appType model.ApplicationType, redirectURI string, l *logs.Log) (string, map[string]interface{}, error) {
return "", nil, errors.New(logutils.Unimplemented)
oauth2Config, err := a.getOAuth2AuthConfig(authType, appType)
if err != nil {
return "", nil, errors.WrapErrorAction(logutils.ActionGet, typeOAuth2AuthConfig, nil, err)
}

//TODO: necessary?
responseParams := map[string]interface{}{
"redirect_uri": redirectURI,
}

bodyData := map[string]string{
"client_id": oauth2Config.ClientID,
"redirect_uri": redirectURI,
"scope": oauth2Config.Scopes,
"login": "", //TODO: propt user with specific account to use (optional)
"allow_aignup": strconv.FormatBool(oauth2Config.AllowSignUp),
}

//TODO: will need to store state variable to make use of this
if oauth2Config.UseState {
state, err := generateState()
if err != nil {
return "", nil, errors.WrapErrorAction("generating", "random state", nil, err)
}
bodyData["state"] = state
}

authURL := oauth2Config.Host + "/login/oauth/authorize"
if len(oauth2Config.AuthorizeURL) > 0 {
authURL = oauth2Config.AuthorizeURL
}

query := url.Values{}
for k, v := range bodyData {
query.Set(k, v)
}
return authURL + "?" + query.Encode(), responseParams, nil
}

func (a *oauth2AuthImpl) getOAuth2AuthConfig(authType model.AuthType, appType model.ApplicationType) (*oauth2AuthConfig, error) {
errFields := &logutils.FieldArgs{"auth_type_id": authType.ID, "app_type_id": appType}

identityProviderID, ok := authType.Params["identity_provider"].(string)
if !ok {
return nil, errors.ErrorData(logutils.StatusInvalid, "identity provider", errFields)
}
appTypeID := appType.ID
authConfig, err := a.auth.getCachedIdentityProviderConfig(identityProviderID, appTypeID)
if err != nil {
return nil, errors.WrapErrorAction(logutils.ActionFind, model.TypeIdentityProviderConfig, errFields, err)
}

configBytes, err := json.Marshal(authConfig.Config)
if err != nil {
return nil, errors.WrapErrorAction(logutils.ActionMarshal, model.TypeIdentityProviderConfig, errFields, err)
}

var oauth2Config oauth2AuthConfig
err = json.Unmarshal(configBytes, &oauth2Config)
if err != nil {
return nil, errors.WrapErrorAction(logutils.ActionUnmarshal, model.TypeIdentityProviderConfig, errFields, err)
}

validate := validator.New()
err = validate.Struct(oauth2Config)
if err != nil {
return nil, errors.WrapErrorAction(logutils.ActionValidate, model.TypeIdentityProviderConfig, errFields, err)
}

return &oauth2Config, nil
}

func (a *oauth2AuthImpl) checkToken(idToken string, authType model.AuthType, appType model.ApplicationType, oidcConfig *oidcAuthConfig, l *logs.Log) (string, error) {
return "", errors.New(logutils.Unimplemented)
// --- Helper functions ---

// generateState generates and returns a randomized state string
func generateState() (string, error) {
state, err := utils.GenerateRandomString(50)
if err != nil {
return "", errors.WrapErrorAction("generating", "state string", nil, err)
}

return state, nil
}

// initOAuth2Auth initializes and registers a new OAuth2 auth instance
Expand Down

0 comments on commit eb9f30b

Please sign in to comment.