@@ -293,10 +293,15 @@ func configureGiteaOauth(parentHandler *Handler, r *mux.Router, app *App) { | |||||
ClientID: app.Config().GiteaOauth.ClientID, | ClientID: app.Config().GiteaOauth.ClientID, | ||||
ClientSecret: app.Config().GiteaOauth.ClientSecret, | ClientSecret: app.Config().GiteaOauth.ClientSecret, | ||||
ExchangeLocation: app.Config().GiteaOauth.Host + "/login/oauth/access_token", | ExchangeLocation: app.Config().GiteaOauth.Host + "/login/oauth/access_token", | ||||
InspectLocation: app.Config().GiteaOauth.Host + "/api/v1/user", | |||||
InspectLocation: app.Config().GiteaOauth.Host + "/login/oauth/userinfo", | |||||
AuthLocation: app.Config().GiteaOauth.Host + "/login/oauth/authorize", | AuthLocation: app.Config().GiteaOauth.Host + "/login/oauth/authorize", | ||||
HttpClient: config.DefaultHTTPClient(), | HttpClient: config.DefaultHTTPClient(), | ||||
CallbackLocation: callbackLocation, | CallbackLocation: callbackLocation, | ||||
Scope: "openid profile email", | |||||
MapUserID: "sub", | |||||
MapUsername: "login", | |||||
MapDisplayName: "full_name", | |||||
MapEmail: "email", | |||||
} | } | ||||
configureOauthRoutes(parentHandler, r, app, oauthClient, callbackProxy) | configureOauthRoutes(parentHandler, r, app, oauthClient, callbackProxy) | ||||
} | } | ||||
@@ -355,7 +360,7 @@ func (h oauthHandler) viewOauthCallback(app *App, w http.ResponseWriter, r *http | |||||
} | } | ||||
if localUserID != -1 && attachUserID > 0 { | if localUserID != -1 && attachUserID > 0 { | ||||
if err = addSessionFlash(app, w, r, "This Slack account is already attached to another user.", nil); err != nil { | |||||
if err = addSessionFlash(app, w, r, "This OAuth account is already attached to another user.", nil); err != nil { | |||||
return impart.HTTPError{Status: http.StatusInternalServerError, Message: err.Error()} | return impart.HTTPError{Status: http.StatusInternalServerError, Message: err.Error()} | ||||
} | } | ||||
return impart.HTTPError{http.StatusFound, "/me/settings"} | return impart.HTTPError{http.StatusFound, "/me/settings"} | ||||
@@ -376,6 +381,7 @@ func (h oauthHandler) viewOauthCallback(app *App, w http.ResponseWriter, r *http | |||||
} | } | ||||
if attachUserID > 0 { | if attachUserID > 0 { | ||||
log.Info("attaching to user %d", attachUserID) | log.Info("attaching to user %d", attachUserID) | ||||
log.Info("OAuth userid: %s", tokenInfo.UserID) | |||||
err = h.DB.RecordRemoteUserID(r.Context(), attachUserID, tokenInfo.UserID, provider, clientID, tokenResponse.AccessToken) | err = h.DB.RecordRemoteUserID(r.Context(), attachUserID, tokenInfo.UserID, provider, clientID, tokenResponse.AccessToken) | ||||
if err != nil { | if err != nil { | ||||
return impart.HTTPError{http.StatusInternalServerError, err.Error()} | return impart.HTTPError{http.StatusInternalServerError, err.Error()} | ||||
@@ -3,6 +3,8 @@ package writefreely | |||||
import ( | import ( | ||||
"context" | "context" | ||||
"errors" | "errors" | ||||
"fmt" | |||||
"github.com/writeas/web-core/log" | |||||
"net/http" | "net/http" | ||||
"net/url" | "net/url" | ||||
"strings" | "strings" | ||||
@@ -15,6 +17,11 @@ type giteaOauthClient struct { | |||||
ExchangeLocation string | ExchangeLocation string | ||||
InspectLocation string | InspectLocation string | ||||
CallbackLocation string | CallbackLocation string | ||||
Scope string | |||||
MapUserID string | |||||
MapUsername string | |||||
MapDisplayName string | |||||
MapEmail string | |||||
HttpClient HttpClient | HttpClient HttpClient | ||||
} | } | ||||
@@ -46,7 +53,7 @@ func (c giteaOauthClient) buildLoginURL(state string) (string, error) { | |||||
q.Set("redirect_uri", c.CallbackLocation) | q.Set("redirect_uri", c.CallbackLocation) | ||||
q.Set("response_type", "code") | q.Set("response_type", "code") | ||||
q.Set("state", state) | q.Set("state", state) | ||||
// q.Set("scope", "read_user") | |||||
q.Set("scope", c.Scope) | |||||
u.RawQuery = q.Encode() | u.RawQuery = q.Encode() | ||||
return u.String(), nil | return u.String(), nil | ||||
} | } | ||||
@@ -55,7 +62,7 @@ func (c giteaOauthClient) exchangeOauthCode(ctx context.Context, code string) (* | |||||
form := url.Values{} | form := url.Values{} | ||||
form.Add("grant_type", "authorization_code") | form.Add("grant_type", "authorization_code") | ||||
form.Add("redirect_uri", c.CallbackLocation) | form.Add("redirect_uri", c.CallbackLocation) | ||||
// form.Add("scope", "read_user") | |||||
form.Add("scope", c.Scope) | |||||
form.Add("code", code) | form.Add("code", code) | ||||
req, err := http.NewRequest("POST", c.ExchangeLocation, strings.NewReader(form.Encode())) | req, err := http.NewRequest("POST", c.ExchangeLocation, strings.NewReader(form.Encode())) | ||||
if err != nil { | if err != nil { | ||||
@@ -103,12 +110,24 @@ func (c giteaOauthClient) inspectOauthAccessToken(ctx context.Context, accessTok | |||||
return nil, errors.New("unable to inspect access token") | return nil, errors.New("unable to inspect access token") | ||||
} | } | ||||
var inspectResponse InspectResponse | |||||
if err := limitedJsonUnmarshal(resp.Body, infoRequestMaxLen, &inspectResponse); err != nil { | |||||
// since we don't know what the JSON from the server will look like, we create a | |||||
// generic interface and then map manually to values set in the config | |||||
var genericInterface map[string]interface{} | |||||
if err := limitedJsonUnmarshal(resp.Body, infoRequestMaxLen, &genericInterface); err != nil { | |||||
return nil, err | return nil, err | ||||
} | } | ||||
if inspectResponse.Error != "" { | |||||
return nil, errors.New(inspectResponse.Error) | |||||
// map each relevant field in inspectResponse to the mapped field from the config | |||||
var inspectResponse InspectResponse | |||||
inspectResponse.UserID, _ = genericInterface[c.MapUserID].(string) | |||||
// log.Info("Userid from Gitea: %s", inspectResponse.UserID) | |||||
if inspectResponse.UserID == "" { | |||||
log.Error("[CONFIGURATION ERROR] Gitea OAuth provider returned empty UserID value (`%s`).\n Do you need to configure a different `map_user_id` value for this provider?", c.MapUserID) | |||||
return nil, fmt.Errorf("no UserID (`%s`) value returned", c.MapUserID) | |||||
} | } | ||||
inspectResponse.Username, _ = genericInterface[c.MapUsername].(string) | |||||
inspectResponse.DisplayName, _ = genericInterface[c.MapDisplayName].(string) | |||||
inspectResponse.Email, _ = genericInterface[c.MapEmail].(string) | |||||
return &inspectResponse, nil | return &inspectResponse, nil | ||||
} | } |