diff --git a/docs/web/authentication.md b/docs/web/authentication.md index 6d980d1092..434040a2de 100644 --- a/docs/web/authentication.md +++ b/docs/web/authentication.md @@ -9,28 +9,26 @@ the results stored on a server. Table of Contents ================= -- [CodeChecker authentication subsystem](#codechecker-authentication-subsystem) -- [Table of Contents](#table-of-contents) -- [Server-side configuration ](#server-side-configuration-) - - [Dictionary authentication ](#dictionary-authentication-) - - [External authentication methods ](#external-authentication-methods-) - - [PAM authentication ](#pam-authentication-) - - [LDAP authentication ](#ldap-authentication-) - - [Configuration options ](#configuration-options-) - - [Membership in custom groups with regex\_groups](#membership-in-custom-groups-with-regex_groups) - - [OAUTH authentication ](#oauth-authentication-) - - [OAUTH Configuration options ](#oauth-configuration-options-) - - [Details per each provider ](#details-per-each-provider-) -- [Client-side configuration ](#client-side-configuration-) - - [Web-browser client ](#web-browser-client-) - - [Command-line client ](#command-line-client-) - - [Preconfigured credentials ](#preconfigured-credentials-) - - [Automatic login ](#automatic-login-) - - [Currently active tokens ](#currently-active-tokens-) -- [Personal access token ](#personal-access-token-) - - [New personal access token ](#new-personal-access-token-) - - [List personal access tokens ](#list-personal-access-tokens-) - - [Remove personal access token ](#remove-personal-access-token-) +* [Server-side configuration](#server-side-configuration) + * [Dictionary authentication](#dictionary-authentication) + * [External authentication methods](#external-auth-methods) + * [PAM authentication](#pam-authentication) + * [LDAP authentication](#ldap-authentication) + * [Configuration options](#configuration-options) + * Membership in custom groups with [regex_groups](#regex_groups-authentication) + * [OAUTH authentication](#oauth-authentication) + * [OAUTH Configuration options](#oauth-configuration-options) + * [OAUTH details per each provider](#oauth-details-per-each-provider) +* [Client-side configuration](#client-side-configuration) + * [Web-browser client](#web-browser-client) + * [Command-line client](#command-line-client) + * [Preconfigured credentials](#preconfigured-credentials) + * [Automatic login](#automatic-login) + * [Currently active tokens](#currently-active-tokens) +* [Personal access token](#personal-access-token) + * [`new`](#new-personal-access-token) + * [`list`](#list-personal-access-token) + * [`del`](#remove-personal-access-token) # Server-side configuration @@ -386,7 +384,7 @@ CodeChecker also supports OAUTH-based authentication. The `authentication.method Field for the fullname. * `allowed_users` - A list of allowed users differently configured for each provider + A list of allowed users differently configured for each provider ~~~{.json} "method_oauth": { @@ -435,7 +433,7 @@ CodeChecker also supports OAUTH-based authentication. The `authentication.method } ~~~ -#### Details per each provider +#### Oauth Details per each provider * For Google OAuth to function correctly, the `oauth_redirect_uri` in application's configuration must exactly match the `Authorized redirect URIs` specified in the Google API Console. diff --git a/web/api/authentication.thrift b/web/api/authentication.thrift index ffa722abcc..69863de719 100644 --- a/web/api/authentication.thrift +++ b/web/api/authentication.thrift @@ -70,12 +70,8 @@ service codeCheckerAuthentication { throws (1: codechecker_api_shared.RequestFailed requestError), // Create a link for the user to log in for github Oauth. - string createLinkGithub() - throws (1: codechecker_api_shared.RequestFailed requestError), - - // Create a link for the use to log in for google Oauth - string createLinkGoogle() - throws (1: codechecker_api_shared.RequestFailed requestError), + string createLink(1: string provider) + throws (1: codechecker_api_shared.RequestFailed requestError), // Performs logout action for the user. Must be called from the // corresponding valid session which is to be destroyed. diff --git a/web/api/js/codechecker-api-node/dist/codechecker-api-6.59.0.tgz b/web/api/js/codechecker-api-node/dist/codechecker-api-6.59.0.tgz index 943c3eb0d2..da824de168 100644 Binary files a/web/api/js/codechecker-api-node/dist/codechecker-api-6.59.0.tgz and b/web/api/js/codechecker-api-node/dist/codechecker-api-6.59.0.tgz differ diff --git a/web/api/py/codechecker_api/dist/codechecker_api.tar.gz b/web/api/py/codechecker_api/dist/codechecker_api.tar.gz index f8b3113ab9..855d9f72bc 100644 Binary files a/web/api/py/codechecker_api/dist/codechecker_api.tar.gz and b/web/api/py/codechecker_api/dist/codechecker_api.tar.gz differ diff --git a/web/api/py/codechecker_api_shared/dist/codechecker_api_shared.tar.gz b/web/api/py/codechecker_api_shared/dist/codechecker_api_shared.tar.gz index 7ee02c0f4a..58598fdf7a 100644 Binary files a/web/api/py/codechecker_api_shared/dist/codechecker_api_shared.tar.gz and b/web/api/py/codechecker_api_shared/dist/codechecker_api_shared.tar.gz differ diff --git a/web/client/codechecker_client/client.py b/web/client/codechecker_client/client.py index aa85c10ecf..a9c748d6b0 100644 --- a/web/client/codechecker_client/client.py +++ b/web/client/codechecker_client/client.py @@ -13,7 +13,7 @@ import getpass import sys from thrift.Thrift import TApplicationException -from authlib.integrations.requests_client import OAuth2Session + import codechecker_api_shared from codechecker_api.Authentication_v6 import ttypes as AuthTypes @@ -136,7 +136,7 @@ def login_user(protocol, host, port, username, login=False): sys.exit(1) -def perform_auth_for_handler(auth_client, host, port, manager): +def perform_auth_for_handler(auth_client, host, port, manager): # Before actually communicating with the server, # we need to check authentication first. diff --git a/web/client/codechecker_client/helpers/authentication.py b/web/client/codechecker_client/helpers/authentication.py index 06a33bdeb6..7e4882503d 100644 --- a/web/client/codechecker_client/helpers/authentication.py +++ b/web/client/codechecker_client/helpers/authentication.py @@ -11,7 +11,7 @@ from codechecker_api.Authentication_v6 import codeCheckerAuthentication -from codechecker_client.thrift_call import ThriftClientCall +from codechecker_client.thrift_call import thrift_client_call from .base import BaseClientHelper @@ -21,74 +21,70 @@ def __init__(self, protocol, host, port, uri, session_token=None): self.client = codeCheckerAuthentication.Client(self.protocol) - @ThriftClientCall + @thrift_client_call def checkAPIVersion(self): pass # ============= Authentication and session handling ============= - @ThriftClientCall + @thrift_client_call def getAuthParameters(self): pass - @ThriftClientCall + @thrift_client_call def getAcceptedAuthMethods(self): pass - @ThriftClientCall + @thrift_client_call def getAccessControl(self): pass - @ThriftClientCall + @thrift_client_call def performLogin(self, auth_method, auth_string): pass - - @ThriftClientCall - def createLinkGithub(self): - pass - @ThriftClientCall - def createLinkGoogle(self): + @thrift_client_call + def createLink(self, provider): pass - @ThriftClientCall + @thrift_client_call def destroySession(self): pass # ============= Authorization, permission management ============= - @ThriftClientCall + @thrift_client_call def getPermissions(self, scope): pass - @ThriftClientCall + @thrift_client_call def getPermissionsForUser(self, scope, extra_params, filter): pass - @ThriftClientCall + @thrift_client_call def getAuthorisedNames(self, permission, extra_params): pass - @ThriftClientCall + @thrift_client_call def addPermission(self, permission, auth_name, is_group, extra_params): pass - @ThriftClientCall + @thrift_client_call def removePermission(self, permission, auth_name, is_group, extra_params): pass - @ThriftClientCall + @thrift_client_call def hasPermission(self, permission, extra_params): pass # ============= Token management ============= - @ThriftClientCall + @thrift_client_call def newToken(self, description): pass - @ThriftClientCall + @thrift_client_call def removeToken(self, token): pass - @ThriftClientCall + @thrift_client_call def getTokens(self): pass diff --git a/web/server/codechecker_server/api/authentication.py b/web/server/codechecker_server/api/authentication.py index e10458a382..76094ff58b 100644 --- a/web/server/codechecker_server/api/authentication.py +++ b/web/server/codechecker_server/api/authentication.py @@ -10,6 +10,8 @@ """ from authlib.integrations.requests_client import OAuth2Session +from authlib.common.security import generate_token + import json import codechecker_api_shared @@ -30,7 +32,6 @@ from ..server import permissions from ..session_manager import generate_session_token -from authlib.common.security import generate_token LOG = get_logger('server') @@ -97,59 +98,56 @@ def getLoggedInUser(self): else: return "" - @timeit - def createLinkGithub(self): - """ - This functin is for creating a autehntication link for OAuth for Github. - """ - self.oauth_config = self.oauth_config_github - - if not self.oauth_config.get("enabled"): - raise codechecker_api_shared.ttypes.RequestFailed( - codechecker_api_shared.ttypes.ErrorCode.AUTH_DENIED, - "OAuth authentication is not enabled.11") - - client_id = self.oauth_config["oauth_client_id"] - client_secret = self.oauth_config["oauth_client_secret"] - scope = self.oauth_config["oauth_scope"] - authorization_uri = self.oauth_config["oauth_authorization_uri"] - - # Create an OAuth2Session instance - session = OAuth2Session(client_id, client_secret, scope=scope) - url, _ = session.create_authorization_url(authorization_uri) - - return url - @timeit - def createLinkGoogle(self): + def createLink(self, provider): """ - This function is for creating an authentication link for OAuth for Google. + This functin is for creating a autehntication link for OAuth for specified provider """ - oauth_config = self.oauth_config_google # get the google oauth config + url = None + print("createLink function called") + if provider == "github": + self.oauth_config = self.oauth_config_github - if not oauth_config.get("enabled"): - raise codechecker_api_shared.ttypes.RequestFailed( - codechecker_api_shared.ttypes.ErrorCode.AUTH_DENIED, - "OAuth authentication is not enabled. 22") + if not self.oauth_config.get("enabled"): + raise codechecker_api_shared.ttypes.RequestFailed( + codechecker_api_shared.ttypes.ErrorCode.AUTH_DENIED, + "OAuth authentication is not enabled.11") - client_id = oauth_config["oauth_client_id"] - client_secret = oauth_config["oauth_client_secret"] - scope = oauth_config["oauth_scope"] - authorization_uri = oauth_config["oauth_authorization_uri"] - redirect_uri = oauth_config["oauth_redirect_uri"] - + client_id = self.oauth_config["oauth_client_id"] + client_secret = self.oauth_config["oauth_client_secret"] + scope = self.oauth_config["oauth_scope"] + authorization_uri = self.oauth_config["oauth_authorization_uri"] - # Create an OAuth2Session instance - session = OAuth2Session(client_id, client_secret, scope=scope, redirect_uri=redirect_uri) + # Create an OAuth2Session instance + session = OAuth2Session(client_id, client_secret, scope=scope) + #Create authorization URL + url, _ = session.create_authorization_url(authorization_uri) - # Create authorization URL - nonce = generate_token() - authorization_url, state = session.create_authorization_url(authorization_uri, nonce=nonce) + elif provider == "google": + oauth_config = self.oauth_config_google # get the google oauth config - - return authorization_url + if not oauth_config.get("enabled"): + raise codechecker_api_shared.ttypes.RequestFailed( + codechecker_api_shared.ttypes.ErrorCode.AUTH_DENIED, + "OAuth authentication is not enabled. 22") + client_id = oauth_config["oauth_client_id"] + client_secret = oauth_config["oauth_client_secret"] + scope = oauth_config["oauth_scope"] + authorization_uri = oauth_config["oauth_authorization_uri"] + redirect_uri = oauth_config["oauth_redirect_uri"] + # Create an OAuth2Session instance + session = OAuth2Session( + client_id, + client_secret, + scope=scope, + redirect_uri=redirect_uri) + + # Create authorization URL + nonce = generate_token() + url = session.create_authorization_url(authorization_uri, nonce=nonce)[0] + return url @timeit def getAcceptedAuthMethods(self): @@ -220,8 +218,8 @@ def performLogin(self, auth_method, auth_string): LOG.info("'%s' logged in.", user_name) return session.token else: - msg = "Invalid credentials supplied for user '{0}'. " \ - "Refusing authentication!".format(user_name) + msg = f"Invalid credentials supplied for user " \ + f"'{user_name}'. Refusing authentication!" LOG.warning(msg) raise codechecker_api_shared.ttypes.RequestFailed( @@ -229,46 +227,54 @@ def performLogin(self, auth_method, auth_string): msg) elif auth_method == "oauth_github": LOG.info("OAuth login... started") - + oauth_config = self.oauth_config_github if not oauth_config.get("enabled"): raise codechecker_api_shared.ttypes.RequestFailed( codechecker_api_shared.ttypes.ErrorCode.AUTH_DENIED, "OAuth authentication is not enabled.33") - + client_id = oauth_config["oauth_client_id"] client_secret = oauth_config["oauth_client_secret"] scope = oauth_config["oauth_scope"] token_url = oauth_config["oauth_token_uri"] user_info_url = oauth_config["oauth_user_info_uri"] - + session = OAuth2Session(client_id, client_secret, scope=scope) token = session.fetch_token( url=token_url, authorization_response=f"{auth_string}", ) - - user_info = session.get(user_info_url).json() + user_info = session.get(user_info_url).json() username = user_info[oauth_config["oauth_user_info_mapping"]["username"]] - if username not in oauth_config.get("allowed_users", []): + allowed_users = oauth_config.get("allowed_users", []) + # important process here + if allowed_users == ["*"] or username in allowed_users: + session = self.__manager.create_session( + "github@" + username + ":" + token['access_token']) + return session.token + + if len(allowed_users) == 0: raise codechecker_api_shared.ttypes.RequestFailed( codechecker_api_shared.ttypes.ErrorCode.AUTH_DENIED, - "User is not authorized to access this service.") + "The allowed users list is empty") - session = self.__manager.create_session("github@" + username + ":" + token['access_token']) - return session.token + raise codechecker_api_shared.ttypes.RequestFailed( + codechecker_api_shared.ttypes.ErrorCode.AUTH_DENIED, + "User is not authorized to access this service") + elif auth_method == "oauth_google": LOG.info("OAuth login GOOGLE... started") - + oauth_config = self.oauth_config_google if not oauth_config.get("enabled"): raise codechecker_api_shared.ttypes.RequestFailed( codechecker_api_shared.ttypes.ErrorCode.AUTH_DENIED, "OAuth authentication is not enabled.44") - + client_id = oauth_config["oauth_client_id"] client_secret = oauth_config["oauth_client_secret"] scope = oauth_config["oauth_scope"] @@ -276,12 +282,15 @@ def performLogin(self, auth_method, auth_string): user_info_url = oauth_config["oauth_user_info_uri"] redirect_uri = oauth_config["oauth_redirect_uri"] - session = OAuth2Session(client_id, client_secret, scope=scope, redirect_uri=redirect_uri) + session = OAuth2Session( + client_id, + client_secret, + scope=scope, + redirect_uri=redirect_uri) token = session.fetch_token( url=token_url, - authorization_response=f"{auth_string}", - ) - + authorization_response=f"{auth_string}") + user_info = session.get(user_info_url).json() email = user_info[oauth_config["oauth_user_info_mapping"]["email"]] if email not in oauth_config.get("allowed_users", []): @@ -290,14 +299,13 @@ def performLogin(self, auth_method, auth_string): "User is not authorized to access this service.") session = self.__manager.create_session("google@" + email + ":" + token['access_token']) - + return session.token raise codechecker_api_shared.ttypes.RequestFailed( codechecker_api_shared.ttypes.ErrorCode.AUTH_DENIED, "Could not negotiate via common authentication method.") - @timeit def destroySession(self): user_name = self.getLoggedInUser() diff --git a/web/server/codechecker_server/session_manager.py b/web/server/codechecker_server/session_manager.py index c56751a920..54cfa03ab0 100644 --- a/web/server/codechecker_server/session_manager.py +++ b/web/server/codechecker_server/session_manager.py @@ -246,13 +246,7 @@ def __init__(self, configuration_file, root_sha, force_auth=False): if 'method_oauth' in self.__auth_config and \ self.__auth_config['method_oauth'].get('enabled'): - if 'oauth' not in UNSUPPORTED_METHODS: - found_auth_method = True - else: - LOG.warning("OAuth authentication was enabled but " - "prerequisites are NOT installed on the system" - "... Disabling OAuth authentication.") - self.__auth_config['method_oauth']['enabled'] = False + found_auth_method = True if not found_auth_method: if force_auth: @@ -265,7 +259,7 @@ def __init__(self, configuration_file, root_sha, force_auth=False): "authentication backends are configured... " "Falling back to no authentication.") self.__auth_config['enabled'] = False - + def get_oauth_config(self, provider): return self.__auth_config.get('method_oauth', {}).get("providers", {}).get(provider, {}) @@ -507,21 +501,23 @@ def __try_auth_oauth_github(self, auth_string): """ Try to authenticate user based on the OAuth configuration. """ + username, token = None, None if self.__is_method_enabled('oauth') and 'github@' in auth_string: data = auth_string.split('github@')[1] username, token = data.split(':') - return {'username': username, 'token': token } + return {'username': username, 'token': token } def __try_auth_oauth_google(self, auth_string): """ Try to authenticate user based on the OAuth configuration. """ + email, token = None, None if self.__is_method_enabled('oauth') and 'google@' in auth_string: data = auth_string.split('google@')[1] email, token = data.split(':') - return {'username': email, 'token': token } + return {'username': email, 'token': token } def __update_groups(self, user_name, groups): """ diff --git a/web/server/config/server_config.json b/web/server/config/server_config.json index 83bbecd060..4e37556d2b 100644 --- a/web/server/config/server_config.json +++ b/web/server/config/server_config.json @@ -14,44 +14,56 @@ "max_probe": 10 }, "authentication": { - "enabled": false, - "realm_name": "CodeChecker Privileged server", - "realm_error": "Access requires valid credentials.", - "session_lifetime": 300, - "refresh_time": 60, - "logins_until_cleanup": 30, + "enabled" : false, + "realm_name" : "CodeChecker Privileged server", + "realm_error" : "Access requires valid credentials.", + "session_lifetime" : 300, + "refresh_time" : 60, + "logins_until_cleanup" : 30, "method_dictionary": { - "enabled": false, - "auths": [], - "groups": {} + "enabled" : false, + "auths" : [], + "groups" : {} }, "method_ldap": { - "enabled": false, + "enabled" : false, "authorities": [ { - "connection_url": "ldap://ldap.example.org", - "username": null, - "password": null, - "referrals": false, - "deref": "always", - "accountBase": null, - "accountScope": "subtree", - "accountPattern": "(&(objectClass=person)(sAMAccountName=$USN$))", + "connection_url" : "ldap://ldap.example.org", + "username" : null, + "password" : null, + "referrals" : false, + "deref" : "always", + "accountBase" : null, + "accountScope" : "subtree", + "accountPattern" : "(&(objectClass=person)(sAMAccountName=$USN$))", "user_dn_postfix_preference": null, - "groupBase": null, - "groupScope": "subtree", - "groupPattern": "(&(objectClass=group)(member=$USERDN$))", - "groupNameAttr": "sAMAccountName" + "groupBase" : null, + "groupScope" : "subtree", + "groupPattern" : "(&(objectClass=group)(member=$USERDN$))", + "groupNameAttr" : "sAMAccountName" } ] }, + "method_pam": { + "enabled" : false, + "users": [ + "root", "myname" + ], + "groups": [ + "adm", "cc-users" + ] + }, "method_oauth": { - "enabled": false, - "providers": { - "github": { - "enabled": false, - "oauth_client_id": "client id", - "oauth_client_secret": "client secret", + "enabled": true, + "groups": [ + "allowed_users" + ], + "providers" : { + "github" : { + "enabled" : true, + "oauth_client_id" : "ExampleClientID", + "oauth_client_secret": "exampleClientSecret", "oauth_authorization_uri": "https://github.com/login/oauth/authorize", "oauth_token_uri": "https://github.com/login/oauth/access_token", "oauth_user_info_uri": "https://github.com/user", @@ -68,46 +80,31 @@ ] }, "google": { - "enabled": false, - "oauth_client_id": "client id", - "oauth_client_secret": "client secret", - "oauth_authorization_uri": "https://accounts.google.com/o/oauth2/auth", - "oauth_redirect_uri": "http://localhost:8080/login", - "oauth_token_uri": "https://accounts.google.com/o/oauth2/token", - "oauth_user_info_uri": "https://www.googleapis.com/oauth2/v1/userinfo", - "oauth_scope": "openid email profile", - "oauth_user_info_mapping": { - "username": "email", - "email": "email", - "fullname": "name" + "enabled" : true, + "oauth_client_id" : "ExampleClientID", + "oauth_client_secret" : "exampleClientSecret", + "oauth_authorization_uri" : "https://accounts.google.com/o/oauth2/auth", + "oauth_redirect_uri" : "http://path_To_CodeChecker_Login_Page", + "oauth_token_uri" : "https://accounts.google.com/o/oauth2/token", + "oauth_user_info_uri" : "https://www.googleapis.com/oauth2/v1/userinfo", + "oauth_scope" : "openid email profile", + "oauth_user_info_mapping" : { + "username" : "email", + "email" : "email", + "fullname" : "name" }, "allowed_users": [ - "user1", - "user2", - "user3" + "user1@gmail.com", + "user2@gmail.com", + "user3@gmail.com" ] } } }, - "method_pam": { - "enabled": false, - "users": [ - "root", - "myname" - ], - "groups": [ - "adm", - "cc-users" - ] - }, "regex_groups": { - "enabled": false, - "groups": { - "admins_custom_group": [ - "^admin$", - "^admin_", - "_admin$" - ] + "enabled" : false, + "groups" : { + "admins_custom_group" : [ "^admin$", "^admin_", "_admin$" ] } } } diff --git a/web/server/vue-cli/package-lock.json b/web/server/vue-cli/package-lock.json index 377adafc0d..6947701d5e 100644 --- a/web/server/vue-cli/package-lock.json +++ b/web/server/vue-cli/package-lock.json @@ -5115,7 +5115,7 @@ "node_modules/codechecker-api": { "version": "6.59.0", "resolved": "file:../../api/js/codechecker-api-node/dist/codechecker-api-6.59.0.tgz", - "integrity": "sha512-oMXRh9hybrtklvXRF+EMYz55UWh4iOJ/YmkRfWbgZdWNXlFj8my8niduqMAqghaIlVSkITShi+nty84k2vneYw==", + "integrity": "sha512-j2trsuEdxzxVo9WM0tWjQDcog1UPQqAVVpObYNVesFphH4wsMXeKFxbqhQxYp9XL37u3C6MHqIYTu3X8uHkGJg==", "license": "SEE LICENSE IN LICENSE", "dependencies": { "thrift": "0.13.0-hotfix.1" @@ -21146,7 +21146,7 @@ }, "codechecker-api": { "version": "file:../../api/js/codechecker-api-node/dist/codechecker-api-6.59.0.tgz", - "integrity": "sha512-oMXRh9hybrtklvXRF+EMYz55UWh4iOJ/YmkRfWbgZdWNXlFj8my8niduqMAqghaIlVSkITShi+nty84k2vneYw==", + "integrity": "sha512-j2trsuEdxzxVo9WM0tWjQDcog1UPQqAVVpObYNVesFphH4wsMXeKFxbqhQxYp9XL37u3C6MHqIYTu3X8uHkGJg==", "requires": { "thrift": "0.13.0-hotfix.1" } diff --git a/web/server/vue-cli/src/store/actions.type.js b/web/server/vue-cli/src/store/actions.type.js index 0109504dc7..39bc364edf 100644 --- a/web/server/vue-cli/src/store/actions.type.js +++ b/web/server/vue-cli/src/store/actions.type.js @@ -4,7 +4,6 @@ export const LOGIN = "login"; export const LOGOUT = "logout"; export const OAUTH = "oauth"; - export const GET_CURRENT_PRODUCT = "getCurrentProduct"; export const GET_CURRENT_PRODUCT_CONFIG = "getCurrentProductConfig"; export const GET_PACKAGE_VERSION = "getPackageVersion"; diff --git a/web/server/vue-cli/src/store/modules/auth.js b/web/server/vue-cli/src/store/modules/auth.js index b9d013a3c8..912357db03 100644 --- a/web/server/vue-cli/src/store/modules/auth.js +++ b/web/server/vue-cli/src/store/modules/auth.js @@ -1,4 +1,3 @@ - import { GET_AUTH_PARAMS, GET_LOGGED_IN_USER, @@ -123,14 +122,14 @@ const actions = { }, [OAUTH](provider) { - return new Promise(resolve => { - if (provider === "github") { - resolve(authService.getClient().createLinkGithub()); - } else if (provider === "google") { - resolve(authService.getClient().createLinkGoogle()); - } else { - throw new Error(`Unsupported provider: ${provider}`); - } + return new Promise((resolve, reject) => { + authService.getClient().createLink(provider, + handleThriftError(url => { + resolve(url); + }, err => { + reject(err); + }) + ); }); } }; diff --git a/web/server/vue-cli/src/views/Login.vue b/web/server/vue-cli/src/views/Login.vue index 216678eb57..b3fe84071a 100644 --- a/web/server/vue-cli/src/views/Login.vue +++ b/web/server/vue-cli/src/views/Login.vue @@ -102,8 +102,7 @@