From 0aafd0c36837626151dc4fa826d69718e71031aa Mon Sep 17 00:00:00 2001 From: Darius Kazemi Date: Thu, 22 Oct 2020 12:15:55 -0700 Subject: [PATCH] Generic OAuth userinfo properies now configurable When connecting to a generic OAuth provider, you are never sure what object you'll be receiving from the userinfo endpoint (it isn't actually specified anywhere). So this commit adds mapping values to the generic oauth configuration section of config.ini, allowing the user to specify which keys in the remote endpoint it expects to read the UserID, Username, DisplayName, and Email from. Default values if unspecified remain as they were before this commit. --- config/config.go | 4 ++++ oauth.go | 4 ++++ oauth_generic.go | 28 ++++++++++++++++++++++++---- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/config/config.go b/config/config.go index cfb5999..525b6f3 100644 --- a/config/config.go +++ b/config/config.go @@ -110,6 +110,10 @@ type ( AuthEndpoint string `ini:"auth_endpoint"` Scope string `ini:"scope"` AllowDisconnect bool `ini:"allow_disconnect"` + MapUserID string `ini:"map_user_id"` + MapUsername string `ini:"map_username"` + MapDisplayName string `ini:"map_display_name"` + MapEmail string `ini:"map_email"` } // AppCfg holds values that affect how the application functions diff --git a/oauth.go b/oauth.go index 6cbddff..6f3598f 100644 --- a/oauth.go +++ b/oauth.go @@ -266,6 +266,10 @@ func configureGenericOauth(parentHandler *Handler, r *mux.Router, app *App) { HttpClient: config.DefaultHTTPClient(), CallbackLocation: callbackLocation, Scope: config.OrDefaultString(app.Config().GenericOauth.Scope, "read_user"), + MapUserID: config.OrDefaultString(app.Config().GenericOauth.MapUserID, "user_id"), + MapUsername: config.OrDefaultString(app.Config().GenericOauth.MapUsername, "username"), + MapDisplayName: config.OrDefaultString(app.Config().GenericOauth.MapDisplayName, "-"), + MapEmail: config.OrDefaultString(app.Config().GenericOauth.MapEmail, "email"), } configureOauthRoutes(parentHandler, r, app, oauthClient, callbackProxy) } diff --git a/oauth_generic.go b/oauth_generic.go index cb82ad0..b98cf59 100644 --- a/oauth_generic.go +++ b/oauth_generic.go @@ -16,6 +16,10 @@ type genericOauthClient struct { InspectLocation string CallbackLocation string Scope string + MapUserID string + MapUsername string + MapDisplayName string + MapEmail string HttpClient HttpClient } @@ -104,12 +108,28 @@ func (c genericOauthClient) inspectOauthAccessToken(ctx context.Context, accessT 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 interface{} + if err := limitedJsonUnmarshal(resp.Body, infoRequestMaxLen, &genericInterface); err != nil { return nil, err } - if inspectResponse.Error != "" { - return nil, errors.New(inspectResponse.Error) + + m := genericInterface.(map[string]interface{}) + + // map each relevant field in inspectResponse to the mapped field from the config + var inspectResponse InspectResponse + if (m[c.MapUserID] != nil) { + inspectResponse.UserID = m[c.MapUserID].(string) + } + if (m[c.MapUsername] != nil) { + inspectResponse.Username = m[c.MapUsername].(string) + } + if (m[c.MapDisplayName] != nil) { + inspectResponse.DisplayName = m[c.MapDisplayName].(string) + } + if (m[c.MapEmail] != nil) { + inspectResponse.Email = m[c.MapEmail].(string) } return &inspectResponse, nil