jottacloud: add support whitelabel versions
This commit is contained in:
parent
584e705c0c
commit
8a2d1dbe24
2 changed files with 59 additions and 14 deletions
|
@ -54,6 +54,37 @@ type LoginToken struct {
|
||||||
AuthToken string `json:"auth_token"`
|
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
|
// TokenJSON is the struct representing the HTTP response from OAuth2
|
||||||
// providers returning a token in JSON form.
|
// providers returning a token in JSON form.
|
||||||
type TokenJSON struct {
|
type TokenJSON struct {
|
||||||
|
|
|
@ -49,10 +49,11 @@ const (
|
||||||
rootURL = "https://www.jottacloud.com/jfs/"
|
rootURL = "https://www.jottacloud.com/jfs/"
|
||||||
apiURL = "https://api.jottacloud.com/"
|
apiURL = "https://api.jottacloud.com/"
|
||||||
baseURL = "https://www.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-"
|
cachePrefix = "rclone-jcmd5-"
|
||||||
configDevice = "device"
|
configDevice = "device"
|
||||||
configMountpoint = "mountpoint"
|
configMountpoint = "mountpoint"
|
||||||
|
configTokenURL = "tokenURL"
|
||||||
configVersion = 1
|
configVersion = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -61,8 +62,8 @@ var (
|
||||||
oauthConfig = &oauth2.Config{
|
oauthConfig = &oauth2.Config{
|
||||||
ClientID: "jottacli",
|
ClientID: "jottacli",
|
||||||
Endpoint: oauth2.Endpoint{
|
Endpoint: oauth2.Endpoint{
|
||||||
AuthURL: tokenURL,
|
AuthURL: defaultTokenURL,
|
||||||
TokenURL: tokenURL,
|
TokenURL: defaultTokenURL,
|
||||||
},
|
},
|
||||||
RedirectURL: oauthutil.RedirectLocalhostURL,
|
RedirectURL: oauthutil.RedirectLocalhostURL,
|
||||||
}
|
}
|
||||||
|
@ -85,8 +86,6 @@ func init() {
|
||||||
log.Fatalf("Failed to parse config version - corrupted config")
|
log.Fatalf("Failed to parse config version - corrupted config")
|
||||||
}
|
}
|
||||||
refresh = ver != configVersion
|
refresh = ver != configVersion
|
||||||
} else {
|
|
||||||
refresh = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if refresh {
|
if refresh {
|
||||||
|
@ -109,7 +108,7 @@ func init() {
|
||||||
fmt.Printf("Login Token> ")
|
fmt.Printf("Login Token> ")
|
||||||
loginToken := config.ReadLine()
|
loginToken := config.ReadLine()
|
||||||
|
|
||||||
token, err := doAuth(ctx, srv, loginToken)
|
token, err := doAuth(ctx, srv, loginToken, m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to get oauth token: %s", err)
|
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
|
// 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)
|
loginTokenBytes, err := base64.StdEncoding.DecodeString(loginTokenBase64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return token, err
|
return token, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// decode login token
|
||||||
var loginToken api.LoginToken
|
var loginToken api.LoginToken
|
||||||
decoder := json.NewDecoder(bytes.NewReader(loginTokenBytes))
|
decoder := json.NewDecoder(bytes.NewReader(loginTokenBytes))
|
||||||
err = decoder.Decode(&loginToken)
|
err = decoder.Decode(&loginToken)
|
||||||
|
@ -257,17 +257,22 @@ func doAuth(ctx context.Context, srv *rest.Client, loginTokenBase64 string) (tok
|
||||||
return token, err
|
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{
|
opts := rest.Opts{
|
||||||
Method: "GET",
|
Method: "GET",
|
||||||
RootURL: loginToken.WellKnownLink,
|
RootURL: loginToken.WellKnownLink,
|
||||||
NoResponse: true,
|
|
||||||
}
|
}
|
||||||
_, err = srv.Call(ctx, &opts)
|
var wellKnown api.WellKnown
|
||||||
|
_, err = srv.CallJSON(ctx, &opts, nil, &wellKnown)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return token, err
|
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
|
// prepare out token request with username and password
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
values.Set("client_id", "jottacli")
|
values.Set("client_id", "jottacli")
|
||||||
|
@ -459,6 +464,7 @@ func NewFs(name, root string, m configmap.Mapper) (fs.Fs, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check config version
|
||||||
var ok bool
|
var ok bool
|
||||||
var version string
|
var version string
|
||||||
if version, ok = m.Get("configVersion"); ok {
|
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")
|
return nil, errors.New("Outdated config - please reconfigure this backend")
|
||||||
}
|
}
|
||||||
|
|
||||||
rootIsDir := strings.HasSuffix(root, "/")
|
// if custome endpoints are set use them else stick with defaults
|
||||||
root = parsePath(root)
|
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)
|
baseClient := fshttp.NewClient(fs.Config)
|
||||||
oAuthClient, ts, err := oauthutil.NewClientWithBaseClient(name, m, oauthConfig, baseClient)
|
oAuthClient, ts, err := oauthutil.NewClientWithBaseClient(name, m, oauthConfig, baseClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "Failed to configure Jottacloud oauth client")
|
return nil, errors.Wrap(err, "Failed to configure Jottacloud oauth client")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rootIsDir := strings.HasSuffix(root, "/")
|
||||||
|
root = parsePath(root)
|
||||||
|
|
||||||
f := &Fs{
|
f := &Fs{
|
||||||
name: name,
|
name: name,
|
||||||
root: root,
|
root: root,
|
||||||
|
|
Loading…
Reference in a new issue