1. Authentication Provider
By creating an authentication provider, you can use the user identity of the authentication provider based on the OAuth2.0 protocol to log in to FunShare, thereby achieving single sign-on (SSO).
Single sign-on can be achieved through configuration (based on the OpenID Connect protocol), or create a custom APL code in the "authentication provider" namespace to achieve single sign-on.
1.1 OpenID Connect
If the identity authentication protocol of the authentication provider is based on OpenID Connect, it can be implemented through configuration (OpenID Connect is an interoperable identity authentication protocol based on the OAuth 2.0 specification).

Users need to configure the following information:
-
Provider Type: OpenId Connet
-
Name: Authentication provider name (up to 50 characters)
-
URL Suffix: used to generate Oauth2 SSO login, logout and callback addresses (maximum 50 characters, can only contain underscore and alphanumeric characters. Must start with a letter, exclude spaces, must not end with an underscore, and must not contain two consecutive underscores)
-
Consumer Key: Consumer Key (Client ID) issued by the authentication provider
-
Consumer Secret: Consumer Secret (Client Secret) issued by the authentication provider
-
Token Interface Address: Get the API address of the authentication provider Token
-
User Information Interface Address: the API address for obtaining the user information of the authentication provider
-
Authorization Scope: Provided by the identity verification provider, the permission description that allows access to user information (openid is passed by default when not filled in)
-
External User Authentication Field: Select a field from the user information of the authentication provider as the user authentication field, and you need to ensure the uniqueness of the value of this field
-
ShareCRM User Authentication Field: From ShareCRM personnel object, select a field API Name as the user authentication field, and you need to ensure the uniqueness of this field value
During single sign-on authentication, the field value of the "External User Identity Authentication Field" of the user information returned by the identity verification provider will be used to query the value of the "ShareCRM User Identity Authentication Field" field of the ShareCRM staff. If there is a returned result Then the authentication is successful.
-
Custom Logout Address: The logout address of the authentication provider accessed when single sign-out is required
After saving the configuration, the system will display the generated single sign-on address, callback address and logout address below:
-
Single Sign-on Address: the entry address of single sign-on
-
Callback Address: configure the callback address of the authentication provider
-
Logout Address: configure the single sign-out address of the authentication provider
1.2 Custom Authentication Provider
Non-standardized Oauth2.0 single sign-on is achieved by creating custom APL code in the "Authentication Provider" namespace (currently this namespace only supports Groovy's APL classes).
Code Example:
/**
* @type classes
* @returntype
* @namespace custom_oauth_protocol
*/
class AAA implements AuthProviderPlugin {
/**
* Jump idp login url
* redirect_uri is the callback address generated by the authentication provider
* client_id client id issued by identity authentication provider
* Other parameters can be set in the parameters of this method in turn according to the requirements of the identity authentication provider
*/
@Override
String authorizeUrl() {
String authorizeUrl = "xxx/oauth2/auth"
final Map<String, String> param = [
"response_type": "code",
"response_mode": "query",
"scope" : "openid",
"redirect_uri" : "xxx.my.fxiaoke.com/oauth2/sp/callback/xxx",
"client_id" : "xxxx"
]
return appendUrl(authorizeUrl, param)
}
/**
* idp callback
* @param params The parameters passed in the callback after successful idp login (usually including code)
* @return Return the employee id in FunShare
* This method usually needs to implement logic:
* 1. Obtain the code from the input parameter, and use the code to obtain the token from the identity authentication provider
* 2. After obtaining the token, use the token to obtain the user information of the identity authentication provider (external user information)
* 3. Use external user information to query the corresponding Fanshare user information
* 4. If the queried valid FanShare staff id is returned, it means the authentication is successful. If an invalid FanShare staff id is returned, it means the authentication failed
*/
@Override
Integer callback(Map<String, List<String>> params) {
String token = getAccessToken(params);
log.info(token);
Integer empId = getEmployeeId(token);
log.info(empId);
return empId;
}
/**
* When logging out of FunShare, jump to this address at the same time, and log out of idp
* @return Jump to FunShare login page when returning null
*/
@Override
String logoffUrl() {
return "xxx/oauth2/logoff"
}
private static String appendUrl(String url, Map<String, String> data) {
String paramStr=''
data.each { String key, value -> paramStr += key + value + "&" }
paramStr = paramStr. substring(0, paramStr. length() - 1)
return url. contains("?") ? (url + "&" + paramStr) : (url + "?" + paramStr);
}
private String getAccessToken(Map<String, List<String>> parameterMap) {
FormBody body = FormBody. builder()
.field("client_id", "xxx")
.field("scope", "openid")
.field("redirect_uri", "https://xxx.my.fxiaoke.com/oauth2/sp/callback/xxx")
.field("client_secret", "xxxx")
.field("code", parameterMap["code"].get(0))
.build()
Request request = Request. builder()
.method("POST")
.url("https://xxxx/oauth2/token")
.timeout(7000)
.retryCount(0)
.body(body)
.build()
HttpResult o = (HttpResult) http. execute(request). getData()
log. info(o)
return o.content["access_token"].toString()
}
Integer getEmployeeId(String accessToken) {
HttpResult o = (HttpResult) http.get("https://xxx/oauth2/userinfo", ["Authorization": accessToken]).getData();
String user = o. content["sub"]. toString();
log. info(user)
QueryResult data = (QueryResult) object. find("PersonnelObj",
[["employee_number": user]],
2,
0
).getData()
List<Map> dataList = data. dataList
if (dataList. size() <= 0) {
message.throwErrorMessage("Could not find the corresponding user, user:" + user)
}
if (dataList. size() > 1) {
message.throwErrorMessage("Find multiple corresponding users, user:" + user)
}
return dataList[0]["user_id"].toString() as Integer
}
//The entry method when debugging
static void main(String[] args) {
}
}
After writing the code, bind the code on the authentication provider page to complete the configuration.
