From 8a2d1dbe24fde2970aa8e643db9c36e8ace966c3 Mon Sep 17 00:00:00 2001 From: buengese Date: Sat, 28 Dec 2019 17:45:04 +0100 Subject: [PATCH] jottacloud: add support whitelabel versions --- backend/jottacloud/api/types.go | 31 +++++++++++++++++++++++ backend/jottacloud/jottacloud.go | 42 +++++++++++++++++++++----------- 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/backend/jottacloud/api/types.go b/backend/jottacloud/api/types.go index 83d4db738..fb28d39fa 100644 --- a/backend/jottacloud/api/types.go +++ b/backend/jottacloud/api/types.go @@ -54,6 +54,37 @@ type LoginToken struct { AuthToken string `json:"auth_token"` } +// WellKnown contains some configuration parameters for setting up endpoints +type WellKnown struct { + Issuer string `json:"issuer"` + AuthorizationEndpoint string `json:"authorization_endpoint"` + TokenEndpoint string `json:"token_endpoint"` + TokenIntrospectionEndpoint string `json:"token_introspection_endpoint"` + UserinfoEndpoint string `json:"userinfo_endpoint"` + EndSessionEndpoint string `json:"end_session_endpoint"` + JwksURI string `json:"jwks_uri"` + CheckSessionIframe string `json:"check_session_iframe"` + GrantTypesSupported []string `json:"grant_types_supported"` + ResponseTypesSupported []string `json:"response_types_supported"` + SubjectTypesSupported []string `json:"subject_types_supported"` + IDTokenSigningAlgValuesSupported []string `json:"id_token_signing_alg_values_supported"` + UserinfoSigningAlgValuesSupported []string `json:"userinfo_signing_alg_values_supported"` + RequestObjectSigningAlgValuesSupported []string `json:"request_object_signing_alg_values_supported"` + ResponseNodesSupported []string `json:"response_modes_supported"` + RegistrationEndpoint string `json:"registration_endpoint"` + TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported"` + TokenEndpointAuthSigningAlgValuesSupported []string `json:"token_endpoint_auth_signing_alg_values_supported"` + ClaimsSupported []string `json:"claims_supported"` + ClaimTypesSupported []string `json:"claim_types_supported"` + ClaimsParameterSupported bool `json:"claims_parameter_supported"` + ScopesSupported []string `json:"scopes_supported"` + RequestParameterSupported bool `json:"request_parameter_supported"` + RequestURIParameterSupported bool `json:"request_uri_parameter_supported"` + CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported"` + TLSClientCertificateBoundAccessTokens bool `json:"tls_client_certificate_bound_access_tokens"` + IntrospectionEndpoint string `json:"introspection_endpoint"` +} + // TokenJSON is the struct representing the HTTP response from OAuth2 // providers returning a token in JSON form. type TokenJSON struct { diff --git a/backend/jottacloud/jottacloud.go b/backend/jottacloud/jottacloud.go index 91b987a57..64c6fff33 100644 --- a/backend/jottacloud/jottacloud.go +++ b/backend/jottacloud/jottacloud.go @@ -49,10 +49,11 @@ const ( rootURL = "https://www.jottacloud.com/jfs/" apiURL = "https://api.jottacloud.com/" baseURL = "https://www.jottacloud.com/" - tokenURL = "https://id.jottacloud.com/auth/realms/jottacloud/protocol/openid-connect/token" + defaultTokenURL = "https://id.jottacloud.com/auth/realms/jottacloud/protocol/openid-connect/token" cachePrefix = "rclone-jcmd5-" configDevice = "device" configMountpoint = "mountpoint" + configTokenURL = "tokenURL" configVersion = 1 ) @@ -61,8 +62,8 @@ var ( oauthConfig = &oauth2.Config{ ClientID: "jottacli", Endpoint: oauth2.Endpoint{ - AuthURL: tokenURL, - TokenURL: tokenURL, + AuthURL: defaultTokenURL, + TokenURL: defaultTokenURL, }, RedirectURL: oauthutil.RedirectLocalhostURL, } @@ -85,8 +86,6 @@ func init() { log.Fatalf("Failed to parse config version - corrupted config") } refresh = ver != configVersion - } else { - refresh = true } if refresh { @@ -109,7 +108,7 @@ func init() { fmt.Printf("Login Token> ") loginToken := config.ReadLine() - token, err := doAuth(ctx, srv, loginToken) + token, err := doAuth(ctx, srv, loginToken, m) if err != nil { log.Fatalf("Failed to get oauth token: %s", err) } @@ -244,12 +243,13 @@ func shouldRetry(resp *http.Response, err error) (bool, error) { } // doAuth runs the actual token request -func doAuth(ctx context.Context, srv *rest.Client, loginTokenBase64 string) (token oauth2.Token, err error) { +func doAuth(ctx context.Context, srv *rest.Client, loginTokenBase64 string, m configmap.Mapper) (token oauth2.Token, err error) { loginTokenBytes, err := base64.StdEncoding.DecodeString(loginTokenBase64) if err != nil { return token, err } + // decode login token var loginToken api.LoginToken decoder := json.NewDecoder(bytes.NewReader(loginTokenBytes)) err = decoder.Decode(&loginToken) @@ -257,17 +257,22 @@ func doAuth(ctx context.Context, srv *rest.Client, loginTokenBase64 string) (tok return token, err } - // we don't seem to need any data from this link but the API is not happy if skip it + // retrieve endpoint urls opts := rest.Opts{ - Method: "GET", - RootURL: loginToken.WellKnownLink, - NoResponse: true, + Method: "GET", + RootURL: loginToken.WellKnownLink, } - _, err = srv.Call(ctx, &opts) + var wellKnown api.WellKnown + _, err = srv.CallJSON(ctx, &opts, nil, &wellKnown) if err != nil { return token, err } + // save the tokenurl + oauthConfig.Endpoint.AuthURL = wellKnown.TokenEndpoint + oauthConfig.Endpoint.TokenURL = wellKnown.TokenEndpoint + m.Set(configTokenURL, wellKnown.TokenEndpoint) + // prepare out token request with username and password values := url.Values{} values.Set("client_id", "jottacli") @@ -459,6 +464,7 @@ func NewFs(name, root string, m configmap.Mapper) (fs.Fs, error) { return nil, err } + // Check config version var ok bool var version string if version, ok = m.Get("configVersion"); ok { @@ -472,15 +478,23 @@ func NewFs(name, root string, m configmap.Mapper) (fs.Fs, error) { return nil, errors.New("Outdated config - please reconfigure this backend") } - rootIsDir := strings.HasSuffix(root, "/") - root = parsePath(root) + // if custome endpoints are set use them else stick with defaults + if tokenURL, ok := m.Get(configTokenURL); ok { + oauthConfig.Endpoint.TokenURL = tokenURL + // jottacloud is weird. we need to use the tokenURL as authURL + oauthConfig.Endpoint.AuthURL = tokenURL + } + // Create OAuth Client baseClient := fshttp.NewClient(fs.Config) oAuthClient, ts, err := oauthutil.NewClientWithBaseClient(name, m, oauthConfig, baseClient) if err != nil { return nil, errors.Wrap(err, "Failed to configure Jottacloud oauth client") } + rootIsDir := strings.HasSuffix(root, "/") + root = parsePath(root) + f := &Fs{ name: name, root: root,