code: function() {
          if (_oauth_client_id === "") {
            return $q.reject({error:'invalid_request', error_description:'RedirectLoginServiceProvider.OAuthClientID() not set'});
          }
          if (_oauth_authorize_uri === "") {
            return $q.reject({error:'invalid_request', error_description:'RedirectLoginServiceProvider.OAuthAuthorizeURI() not set'});
          }
          if (_oauth_redirect_uri === "") {
            return $q.reject({error:'invalid_request', error_description:'RedirectLoginServiceProvider.OAuthRedirectURI not set'});
          }
  
          // Never send a local fragment to remote servers
          var returnUri = new URI($location.url()).fragment("");
          var authorizeParams = {
            client_id: _oauth_client_id,
            response_type: 'token',
            state: makeState(returnUri.toString()),
            redirect_uri: _oauth_redirect_uri
          };
  
          if (_oauth_scope) {
            authorizeParams.scope = _oauth_scope;
          }
  
          if (_oauth_token_uri) {
            authorizeParams.response_type = "code";
            // TODO: add PKCE
          }
  
          var deferred = $q.defer();
          var uri = new URI(_oauth_authorize_uri);
          uri.query(authorizeParams);
          authLogger.log("RedirectLoginService.login(), redirecting", uri.toString());
          window.location.href = uri.toString();
          // Return a promise we never intend to keep, because we're redirecting to another page
          return deferred.promise;
        }
docs: Returns a promise that resolves with {user:{...}, token:'...', ttl:X}, or rejects with {error:'...'[,error_description:'...',error_uri:'...']}