diff --git a/lib/authentication/authentication_client.go b/lib/authentication/authentication_client.go new file mode 100644 index 0000000..d82fd0b --- /dev/null +++ b/lib/authentication/authentication_client.go @@ -0,0 +1,281 @@ +package authentication + +import ( + "encoding/base64" + "errors" + "fmt" + "github.com/Authing/authing-go-sdk/lib/constant" + "github.com/Authing/authing-go-sdk/lib/model" + "github.com/Authing/authing-go-sdk/lib/util" + "io/ioutil" + "net/http" + "strings" +) + +type Client struct { + HttpClient *http.Client + AppId string + Protocol constant.ProtocolEnum + Secret string + Host string + RedirectUri string + TokenEndPointAuthMethod constant.AuthMethodEnum + + Log func(s string) +} + +func NewClient(appId string, secret string, host ...string) *Client { + var clientHost string + if len(host) == 0 { + clientHost = constant.CoreAuthingDefaultUrl + } else { + clientHost = host[0] + } + c := &Client{ + HttpClient: nil, + AppId: appId, + Protocol: "", + Secret: secret, + Host: clientHost, + RedirectUri: "", + Log: nil, + } + if c.HttpClient == nil { + c.HttpClient = &http.Client{} + } + return c +} + +func (c *Client) BuildAuthorizeUrlByOidc(params model.OidcParams) (string, error) { + if c.AppId == "" { + return constant.StringEmpty, errors.New("请在初始化 AuthenticationClient 时传入 appId") + } + if c.Protocol != constant.OIDC { + return constant.StringEmpty, errors.New("初始化 AuthenticationClient 传入的 protocol 应为 ProtocolEnum.OIDC") + } + if params.RedirectUri == "" { + return constant.StringEmpty, errors.New("redirectUri 不能为空") + } + var scope = "" + if strings.Contains(params.Scope, "offline_access") { + scope = "consent" + } + dataMap := map[string]string{ + "client_id": util.GetValidValue(params.AppId, c.AppId), + "scope": util.GetValidValue(params.Scope, "openid profile email phone address"), + "state": util.GetValidValue(params.State, util.RandomString(12)), + "nonce": util.GetValidValue(params.Nonce, util.RandomString(12)), + "response_mode": util.GetValidValue(params.ResponseMode, constant.StringEmpty), + "response_type": util.GetValidValue(params.ResponseType, "code"), + "redirect_uri": util.GetValidValue(params.RedirectUri, c.RedirectUri), + "prompt": util.GetValidValue(scope), + } + return c.Host + "/oidc/auth?" + util.GetQueryString(dataMap), nil +} + +func (c *Client) GetAccessTokenByCode(code string) (string, error) { + if c.AppId == "" { + return constant.StringEmpty, errors.New("请在初始化 AuthenticationClient 时传入 appId") + } + if c.Secret == "" && c.TokenEndPointAuthMethod != constant.None { + return constant.StringEmpty, errors.New("请在初始化 AuthenticationClient 时传入 Secret") + } + url := c.Host + "/oidc/token" + + header := map[string]string{ + "Content-Type": "application/x-www-form-urlencoded", + } + + body := map[string]string{ + "client_id": c.AppId, + "client_secret": c.Secret, + "grant_type": "authorization_code", + "code": code, + "redirect_uri": c.RedirectUri, + } + + switch c.TokenEndPointAuthMethod { + case constant.ClientSecretPost: + body["client_id"] = c.AppId + body["client_secret"] = c.Secret + case constant.ClientSecretBasic: + base64String := "Basic " + base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s",c.AppId, c.Secret))) + header["Authorization"] = base64String + default: + body["client_id"] = c.AppId + } + resp, err := c.SendHttpRequest(url,constant.HttpMethodPost,header,body) + return string(resp), err +} + +func (c *Client) GetUserInfoByAccessToken(accessToken string) (string, error) { + if accessToken == constant.StringEmpty { + return constant.StringEmpty, errors.New("accessToken 不能为空") + } + url := c.Host + "/oidc/me?access_token=" + accessToken + resp, err := c.SendHttpRequest(url, constant.HttpMethodGet, nil, nil) + return string(resp), err +} + +func (c *Client) GetNewAccessTokenByRefreshToken (refreshToken string) (string, error) { + if c.Protocol != constant.OIDC && c.Protocol != constant.OAUTH { + return constant.StringEmpty, errors.New("初始化 AuthenticationClient 时传入的 protocol 参数必须为 ProtocolEnum.OAUTH 或 ProtocolEnum.OIDC,请检查参数") + } + if c.Secret == "" && c.TokenEndPointAuthMethod != constant.None { + return constant.StringEmpty, errors.New("请在初始化 AuthenticationClient 时传入 Secret") + } + + url := c.Host + fmt.Sprintf("/%s/token", c.Protocol) + + header := map[string]string{ + "Content-Type": "application/x-www-form-urlencoded", + } + + body := map[string]string{ + "client_id": c.AppId, + "client_secret": c.Secret, + "grant_type": "refresh_token", + "refresh_token": refreshToken, + } + + switch c.TokenEndPointAuthMethod { + case constant.ClientSecretPost: + body["client_id"] = c.AppId + body["client_secret"] = c.Secret + case constant.ClientSecretBasic: + base64String := "Basic " + base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s",c.AppId, c.Secret))) + header["Authorization"] = base64String + default: + body["client_id"] = c.AppId + } + resp, err := c.SendHttpRequest(url,constant.HttpMethodPost,header,body) + return string(resp), err +} + +func (c *Client) IntrospectToken (token string) (string, error) { + url := c.Host + fmt.Sprintf("/%s/token/introspection", c.Protocol) + + header := map[string]string{ + "Content-Type": "application/x-www-form-urlencoded", + } + + body := map[string]string{ + "token": token, + } + + switch c.TokenEndPointAuthMethod { + case constant.ClientSecretPost: + body["client_id"] = c.AppId + body["client_secret"] = c.Secret + case constant.ClientSecretBasic: + base64String := "Basic " + base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s",c.AppId, c.Secret))) + header["Authorization"] = base64String + default: + body["client_id"] = c.AppId + } + resp, err := c.SendHttpRequest(url,constant.HttpMethodPost,header,body) + return string(resp), err +} + +func (c *Client) ValidateToken (req model.ValidateTokenRequest) (string, error) { + if req.IdToken == constant.StringEmpty && req.AccessToken == constant.StringEmpty { + return constant.StringEmpty, errors.New("请传入 AccessToken 或 IdToken") + } + if req.IdToken != constant.StringEmpty && req.AccessToken != constant.StringEmpty { + return constant.StringEmpty, errors.New("AccessToken 和 IdToken 不能同时传入") + } + + url := c.Host + "/api/v2/oidc/validate_token?" + if req.IdToken != constant.StringEmpty { + url += "id_token=" + req.IdToken + } else if req.AccessToken != constant.StringEmpty { + url += "access_token=" + req.AccessToken + } + + resp, err := c.SendHttpRequest(url,constant.HttpMethodGet,nil,nil) + return string(resp), err +} + +func (c *Client) RevokeToken (token string) (string, error) { + if c.Protocol != constant.OIDC && c.Protocol != constant.OAUTH { + return constant.StringEmpty, errors.New("初始化 AuthenticationClient 时传入的 protocol 参数必须为 ProtocolEnum.OAUTH 或 ProtocolEnum.OIDC,请检查参数") + } + if c.Secret == "" && c.TokenEndPointAuthMethod != constant.None { + return constant.StringEmpty, errors.New("请在初始化 AuthenticationClient 时传入 Secret") + } + + url := c.Host + fmt.Sprintf("/%s/token/revocation", c.Protocol) + + header := map[string]string{ + "Content-Type": "application/x-www-form-urlencoded", + } + + body := map[string]string{ + "client_id": c.AppId, + "token": token, + } + + switch c.TokenEndPointAuthMethod { + case constant.ClientSecretPost: + body["client_id"] = c.AppId + body["client_secret"] = c.Secret + case constant.ClientSecretBasic: + base64String := "Basic " + base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s",c.AppId, c.Secret))) + header["Authorization"] = base64String + default: + body["client_id"] = c.AppId + } + resp, err := c.SendHttpRequest(url,constant.HttpMethodPost,header,body) + return string(resp), err +} + +func (c *Client) GetAccessTokenByClientCredentials (req model.GetAccessTokenByClientCredentialsRequest) (string, error) { + if req.Scope == constant.StringEmpty { + return constant.StringEmpty, errors.New("请传入 scope 参数,请看文档:https://docs.authing.cn/v2/guides/authorization/m2m-authz.html") + } + if req.ClientCredentialInput == nil { + return constant.StringEmpty, errors.New("请在调用本方法时传入 ClientCredentialInput 参数,请看文档:https://docs.authing.cn/v2/guides/authorization/m2m-authz.html") + } + + url := c.Host + "/oidc/token" + + header := map[string]string{ + "Content-Type": "application/x-www-form-urlencoded", + } + + body := map[string]string{ + "client_id": req.ClientCredentialInput.AccessKey, + "client_secret": req.ClientCredentialInput.SecretKey, + "grant_type": "client_credentials", + "scope": req.Scope, + } + + resp, err := c.SendHttpRequest(url,constant.HttpMethodPost,header,body) + return string(resp), err +} + +func (c *Client) SendHttpRequest(url string, method string, header map[string]string, body map[string]string) ([]byte, error) { + var form http.Request + form.ParseForm() + if body != nil && len(body) != 0 { + for key, value := range body { + form.Form.Add(key, value) + } + } + reqBody := strings.TrimSpace(form.Form.Encode()) + req, err := http.NewRequest(method, url, strings.NewReader(reqBody)) + if err != nil { + fmt.Println(err) + } + //req.Header.Add("Content-Type", "application/x-www-form-urlencoded") + //增加header选项 + if header != nil && len(header) != 0 { + for key, value := range header { + req.Header.Add(key, value) + } + } + res, err := c.HttpClient.Do(req) + defer res.Body.Close() + respBody, err := ioutil.ReadAll(res.Body) + return respBody, nil +} diff --git a/lib/authentication/authentication_client_test.go b/lib/authentication/authentication_client_test.go new file mode 100644 index 0000000..2065989 --- /dev/null +++ b/lib/authentication/authentication_client_test.go @@ -0,0 +1,128 @@ +package authentication + +import ( + "fmt" + "github.com/Authing/authing-go-sdk/lib/constant" + "github.com/Authing/authing-go-sdk/lib/model" + "testing" +) + +const ( + AppId = "60a6f980dd9a9a7642da768a" + Secret = "5cd4ea7b3603b792aea9a00da9e18f44" +) + +func TestClient_BuildAuthorizeUrlByOidc(t *testing.T) { + authenticationClient := NewClient(AppId, Secret) + authenticationClient.Protocol = constant.OIDC + authenticationClient.TokenEndPointAuthMethod = constant.None + req := model.OidcParams{ + AppId: AppId, + RedirectUri: "https://mvnrepository.com/", + Nonce: "test", + } + resp, err := authenticationClient.BuildAuthorizeUrlByOidc(req) + if err != nil { + fmt.Println(err) + } else { + fmt.Println(resp) + } +} + +func TestClient_GetAccessTokenByCode(t *testing.T) { + authenticationClient := NewClient("60a6f980dd9a9a7642da768a","5cd4ea7b3603b792aea9a00da9e18f44") + authenticationClient.Host = "https://32l5hb-demo.authing.cn" + authenticationClient.RedirectUri = "https://mvnrepository.com/" + authenticationClient.Protocol = constant.OIDC + authenticationClient.TokenEndPointAuthMethod = constant.None + resp, err := authenticationClient.GetAccessTokenByCode("vj-MWd4eRZdmakwobde53RaFZpBON3-khElsrlEZRGm") + if err != nil { + fmt.Println(err) + } else { + fmt.Println(resp) + } + // {"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjQ0bnJHU05YQ3NDLTByd1J5Q0hENjBzdmc0elpLNF9iV2VnQjluOFRhQzQifQ.eyJqdGkiOiJ3NjJmNkVieHYxd19wbEV3YWMwWlIiLCJzdWIiOiI2MGUyNmI2ZjdiMGRkN2MwYWY4M2VjZDkiLCJpYXQiOjE2MjU0OTI3NjUsImV4cCI6MTYyNjcwMjM2NSwic2NvcGUiOiJvcGVuaWQgcGhvbmUgYWRkcmVzcyBwcm9maWxlIGVtYWlsIiwiaXNzIjoiaHR0cHM6Ly8zMmw1aGItZGVtby5hdXRoaW5nLmNuL29pZGMiLCJhdWQiOiI2MGE2Zjk4MGRkOWE5YTc2NDJkYTc2OGEifQ.KOMWqEtbyH3qdBv_bHX3Dof2t_3XBQ7QDg4-x7fIr9W2YtCnwNnqVehOVYjWpcF-pkVyzBlpmKIc6_X9F8GA-oYbdUKJzhxfoAATj1JnRCRs6Wsxpo3U41up1pgXs5B7JS7gVbiw_IucMg4vLYw_QJ_aPgBTkjCkBZVsPf3NRYCd2cVwiZwvoa8GT6jGP9PJ908rJSSSdsqt6JNzydVbJ9a7p4mBhV3WxUAckXePjIE0QDNDe_GxFwFDktkTbLBIJZBL4bSg3pHGQKHiF9wabfjBRfWV8ChRe8i95n7pq-Gw9fw2fKNv7ieC5bK52D1j6R9L5h7wRvTstgiR7p8krQ","expires_in":1209600,"id_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjQ0bnJHU05YQ3NDLTByd1J5Q0hENjBzdmc0elpLNF9iV2VnQjluOFRhQzQifQ.eyJzdWIiOiI2MGUyNmI2ZjdiMGRkN2MwYWY4M2VjZDkiLCJwaG9uZV9udW1iZXIiOm51bGwsInBob25lX251bWJlcl92ZXJpZmllZCI6ZmFsc2UsImFkZHJlc3MiOnsiY291bnRyeSI6bnVsbCwicG9zdGFsX2NvZGUiOm51bGwsInJlZ2lvbiI6bnVsbCwiZm9ybWF0dGVkIjpudWxsfSwiYmlydGhkYXRlIjpudWxsLCJmYW1pbHlfbmFtZSI6bnVsbCwiZ2VuZGVyIjoiVSIsImdpdmVuX25hbWUiOm51bGwsImxvY2FsZSI6bnVsbCwibWlkZGxlX25hbWUiOm51bGwsIm5hbWUiOm51bGwsIm5pY2tuYW1lIjpudWxsLCJwaWN0dXJlIjoiaHR0cHM6Ly9maWxlcy5hdXRoaW5nLmNvL2F1dGhpbmctY29uc29sZS9kZWZhdWx0LXVzZXItYXZhdGFyLnBuZyIsInByZWZlcnJlZF91c2VybmFtZSI6bnVsbCwicHJvZmlsZSI6bnVsbCwidXBkYXRlZF9hdCI6IjIwMjEtMDctMDVUMTM6NDU6MjMuMTc0WiIsIndlYnNpdGUiOm51bGwsInpvbmVpbmZvIjpudWxsLCJlbWFpbCI6Imx1b2ppZWxpbkBhdXRoaW5nLmNuIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJub25jZSI6InRlc3QiLCJhdF9oYXNoIjoiaFVfa2o5NzdjSGUxXzdhdWI3OWY3dyIsImF1ZCI6IjYwYTZmOTgwZGQ5YTlhNzY0MmRhNzY4YSIsImV4cCI6MTYyNjcwMjM2NSwiaWF0IjoxNjI1NDkyNzY1LCJpc3MiOiJodHRwczovLzMybDVoYi1kZW1vLmF1dGhpbmcuY24vb2lkYyJ9.XtLA_hQZqqwUW2GyVwEVhO2BMqNCFMWCkxQGd1FP37tclxnHKsa26wz8oBKNPXsGwEUBIlcyzi9SCTOibl_UlG4hNrHASNkk_2zQcsjO8fidHfXjEyw2UjhDfxsyh1B6xcJIiM8AJIQi5BHJ1FcFzCLxRK81v_kPqQMMHagYXEQhaFNf-otxrBrf9Yc66wuMLKlgKUgAZLyhTqJFpXPIayzss00vIOvbQNTc5XY27M_uUP2-TInIG8dxY-rcxe06PqTWVvLkDx1CMsEC7Ume1wf6lKqGU4kGnSLlXBxrl1-MRd-Q01gosvBvP2r2Tuxb30ZD0-yG4QY9yD9ytTYSPA","scope":"openid phone address profile email","token_type":"Bearer"} +} + +func TestClient_GetUserInfoByAccessToken(t *testing.T) { + authenticationClient := NewClient("60a6f980dd9a9a7642da768a","5cd4ea7b3603b792aea9a00da9e18f44") + authenticationClient.Host = "https://32l5hb-demo.authing.cn" + authenticationClient.RedirectUri = "https://mvnrepository.com/" + authenticationClient.Protocol = constant.OIDC + authenticationClient.TokenEndPointAuthMethod = constant.None + resp, err := authenticationClient.GetUserInfoByAccessToken("eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjQ0bnJHU05YQ3NDLTByd1J5Q0hENjBzdmc0elpLNF9iV2VnQjluOFRhQzQifQ.eyJqdGkiOiJ3NjJmNkVieHYxd19wbEV3YWMwWlIiLCJzdWIiOiI2MGUyNmI2ZjdiMGRkN2MwYWY4M2VjZDkiLCJpYXQiOjE2MjU0OTI3NjUsImV4cCI6MTYyNjcwMjM2NSwic2NvcGUiOiJvcGVuaWQgcGhvbmUgYWRkcmVzcyBwcm9maWxlIGVtYWlsIiwiaXNzIjoiaHR0cHM6Ly8zMmw1aGItZGVtby5hdXRoaW5nLmNuL29pZGMiLCJhdWQiOiI2MGE2Zjk4MGRkOWE5YTc2NDJkYTc2OGEifQ.KOMWqEtbyH3qdBv_bHX3Dof2t_3XBQ7QDg4-x7fIr9W2YtCnwNnqVehOVYjWpcF-pkVyzBlpmKIc6_X9F8GA-oYbdUKJzhxfoAATj1JnRCRs6Wsxpo3U41up1pgXs5B7JS7gVbiw_IucMg4vLYw_QJ_aPgBTkjCkBZVsPf3NRYCd2cVwiZwvoa8GT6jGP9PJ908rJSSSdsqt6JNzydVbJ9a7p4mBhV3WxUAckXePjIE0QDNDe_GxFwFDktkTbLBIJZBL4bSg3pHGQKHiF9wabfjBRfWV8ChRe8i95n7pq-Gw9fw2fKNv7ieC5bK52D1j6R9L5h7wRvTstgiR7p8krQ") + if err != nil { + fmt.Println(err) + } else { + fmt.Println(resp) + } +} + +func TestClient_IntrospectToken(t *testing.T) { + authenticationClient := NewClient("60a6f980dd9a9a7642da768a","5cd4ea7b3603b792aea9a00da9e18f44") + authenticationClient.Host = "https://32l5hb-demo.authing.cn" + authenticationClient.RedirectUri = "https://mvnrepository.com/" + authenticationClient.Protocol = constant.OIDC + authenticationClient.TokenEndPointAuthMethod = constant.None + + resp, err := authenticationClient.IntrospectToken("eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjQ0bnJHU05YQ3NDLTByd1J5Q0hENjBzdmc0elpLNF9iV2VnQjluOFRhQzQifQ.eyJqdGkiOiJ3NjJmNkVieHYxd19wbEV3YWMwWlIiLCJzdWIiOiI2MGUyNmI2ZjdiMGRkN2MwYWY4M2VjZDkiLCJpYXQiOjE2MjU0OTI3NjUsImV4cCI6MTYyNjcwMjM2NSwic2NvcGUiOiJvcGVuaWQgcGhvbmUgYWRkcmVzcyBwcm9maWxlIGVtYWlsIiwiaXNzIjoiaHR0cHM6Ly8zMmw1aGItZGVtby5hdXRoaW5nLmNuL29pZGMiLCJhdWQiOiI2MGE2Zjk4MGRkOWE5YTc2NDJkYTc2OGEifQ.KOMWqEtbyH3qdBv_bHX3Dof2t_3XBQ7QDg4-x7fIr9W2YtCnwNnqVehOVYjWpcF-pkVyzBlpmKIc6_X9F8GA-oYbdUKJzhxfoAATj1JnRCRs6Wsxpo3U41up1pgXs5B7JS7gVbiw_IucMg4vLYw_QJ_aPgBTkjCkBZVsPf3NRYCd2cVwiZwvoa8GT6jGP9PJ908rJSSSdsqt6JNzydVbJ9a7p4mBhV3WxUAckXePjIE0QDNDe_GxFwFDktkTbLBIJZBL4bSg3pHGQKHiF9wabfjBRfWV8ChRe8i95n7pq-Gw9fw2fKNv7ieC5bK52D1j6R9L5h7wRvTstgiR7p8krQ") + if err != nil { + fmt.Println(err) + } else { + fmt.Println(resp) + } +} + +func TestClient_ValidateToken(t *testing.T) { + authenticationClient := NewClient("60a6f980dd9a9a7642da768a","5cd4ea7b3603b792aea9a00da9e18f44") + authenticationClient.Host = "https://32l5hb-demo.authing.cn" + authenticationClient.RedirectUri = "https://mvnrepository.com/" + authenticationClient.Protocol = constant.OIDC + authenticationClient.TokenEndPointAuthMethod = constant.None + req := model.ValidateTokenRequest{ + AccessToken: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjQ0bnJHU05YQ3NDLTByd1J5Q0hENjBzdmc0elpLNF9iV2VnQjluOFRhQzQifQ.eyJqdGkiOiJ3NjJmNkVieHYxd19wbEV3YWMwWlIiLCJzdWIiOiI2MGUyNmI2ZjdiMGRkN2MwYWY4M2VjZDkiLCJpYXQiOjE2MjU0OTI3NjUsImV4cCI6MTYyNjcwMjM2NSwic2NvcGUiOiJvcGVuaWQgcGhvbmUgYWRkcmVzcyBwcm9maWxlIGVtYWlsIiwiaXNzIjoiaHR0cHM6Ly8zMmw1aGItZGVtby5hdXRoaW5nLmNuL29pZGMiLCJhdWQiOiI2MGE2Zjk4MGRkOWE5YTc2NDJkYTc2OGEifQ.KOMWqEtbyH3qdBv_bHX3Dof2t_3XBQ7QDg4-x7fIr9W2YtCnwNnqVehOVYjWpcF-pkVyzBlpmKIc6_X9F8GA-oYbdUKJzhxfoAATj1JnRCRs6Wsxpo3U41up1pgXs5B7JS7gVbiw_IucMg4vLYw_QJ_aPgBTkjCkBZVsPf3NRYCd2cVwiZwvoa8GT6jGP9PJ908rJSSSdsqt6JNzydVbJ9a7p4mBhV3WxUAckXePjIE0QDNDe_GxFwFDktkTbLBIJZBL4bSg3pHGQKHiF9wabfjBRfWV8ChRe8i95n7pq-Gw9fw2fKNv7ieC5bK52D1j6R9L5h7wRvTstgiR7p8krQ", + IdToken: "", + } + resp, err := authenticationClient.ValidateToken(req) + if err != nil { + fmt.Println(err) + } else { + fmt.Println(resp) + } +} + +func TestClient_GetAccessTokenByClientCredentials(t *testing.T) { + authenticationClient := NewClient("60a6f980dd9a9a7642da768a","5cd4ea7b3603b792aea9a00da9e18f44") + authenticationClient.Host = "https://32l5hb-demo.authing.cn" + authenticationClient.RedirectUri = "https://mvnrepository.com/" + authenticationClient.Protocol = constant.OIDC + authenticationClient.TokenEndPointAuthMethod = constant.None + input := model.ClientCredentialInput{ + AccessKey: "", + SecretKey: "", + } + req := model.GetAccessTokenByClientCredentialsRequest{ + Scope: "openid", + ClientCredentialInput: &input, + } + resp, err := authenticationClient.GetAccessTokenByClientCredentials(req) + if err != nil { + fmt.Println(err) + } else { + fmt.Println(resp) + } +} + +func TestClient_RevokeToken(t *testing.T) { + authenticationClient := NewClient("60a6f980dd9a9a7642da768a","5cd4ea7b3603b792aea9a00da9e18f44") + authenticationClient.Host = "https://32l5hb-demo.authing.cn" + authenticationClient.RedirectUri = "https://mvnrepository.com/" + authenticationClient.Protocol = constant.OIDC + authenticationClient.TokenEndPointAuthMethod = constant.None + resp, err := authenticationClient.RevokeToken("eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjQ0bnJHU05YQ3NDLTByd1J5Q0hENjBzdmc0elpLNF9iV2VnQjluOFRhQzQifQ.eyJqdGkiOiJ3NjJmNkVieHYxd19wbEV3YWMwWlIiLCJzdWIiOiI2MGUyNmI2ZjdiMGRkN2MwYWY4M2VjZDkiLCJpYXQiOjE2MjU0OTI3NjUsImV4cCI6MTYyNjcwMjM2NSwic2NvcGUiOiJvcGVuaWQgcGhvbmUgYWRkcmVzcyBwcm9maWxlIGVtYWlsIiwiaXNzIjoiaHR0cHM6Ly8zMmw1aGItZGVtby5hdXRoaW5nLmNuL29pZGMiLCJhdWQiOiI2MGE2Zjk4MGRkOWE5YTc2NDJkYTc2OGEifQ.KOMWqEtbyH3qdBv_bHX3Dof2t_3XBQ7QDg4-x7fIr9W2YtCnwNnqVehOVYjWpcF-pkVyzBlpmKIc6_X9F8GA-oYbdUKJzhxfoAATj1JnRCRs6Wsxpo3U41up1pgXs5B7JS7gVbiw_IucMg4vLYw_QJ_aPgBTkjCkBZVsPf3NRYCd2cVwiZwvoa8GT6jGP9PJ908rJSSSdsqt6JNzydVbJ9a7p4mBhV3WxUAckXePjIE0QDNDe_GxFwFDktkTbLBIJZBL4bSg3pHGQKHiF9wabfjBRfWV8ChRe8i95n7pq-Gw9fw2fKNv7ieC5bK52D1j6R9L5h7wRvTstgiR7p8krQ") + if err != nil { + fmt.Println(err) + } else { + fmt.Println(resp) + } +} diff --git a/lib/constant/constant.go b/lib/constant/constant.go new file mode 100644 index 0000000..6af0e8a --- /dev/null +++ b/lib/constant/constant.go @@ -0,0 +1,3 @@ +package constant + +const StringEmpty = "" diff --git a/lib/constant/enums.go b/lib/constant/enums.go index 8fdf2d4..921998c 100644 --- a/lib/constant/enums.go +++ b/lib/constant/enums.go @@ -1,22 +1,14 @@ package constant const ( - ClientSecretPost = "client_secret_post" -) - -const ( - HttpMethodGet = "GET" + HttpMethodGet = "GET" HttpMethodPost = "POST" ) const ( - //GraphqlServiceUrl = "https://core.authing.cn/graphql/v2" - CoreEndPointProdUrl = "https://core.authing.cn" - //CoreEndPointDevUrl = "https://core.authing.cn" - CoreAuthingDefaultUrl = "https://core.authing.cn" + CoreAuthingDefaultUrl = "https://core.authing.cn" CoreAuthingGraphqlPath = "/graphql/v2" - PublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4xKeUgQ+Aoz7TLfAfs9+paePb5KIofVthEopwrXFkp8OCeocaTHt9ICjTT2QeJh6cZaDaArfZ873GPUn00eOIZ7Ae+TiA2BKHbCvloW3w5Lnqm70iSsUi5Fmu9/2+68GZRH9L7Mlh8cFksCicW2Y2W2uMGKl64GDcIq3au+aqJQIDAQAB" - + PublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4xKeUgQ+Aoz7TLfAfs9+paePb5KIofVthEopwrXFkp8OCeocaTHt9ICjTT2QeJh6cZaDaArfZ873GPUn00eOIZ7Ae+TiA2BKHbCvloW3w5Lnqm70iSsUi5Fmu9/2+68GZRH9L7Mlh8cFksCicW2Y2W2uMGKl64GDcIq3au+aqJQIDAQAB" /** * token 过期时间 @@ -44,9 +36,26 @@ const ( //Websocket 服务器域名 WebsocketHost = "" - SdkType = "SDK" + SdkType = "SDK" SdkVersion = "go:2.0.0" // TokenCacheKeyPrefix token缓存key前缀 TokenCacheKeyPrefix = "token_" ) + +type ProtocolEnum string + +const ( + OAUTH ProtocolEnum = "oauth" + OIDC ProtocolEnum = "oidc" + CAS ProtocolEnum = "cas" + SAML ProtocolEnum = "saml" +) + +type AuthMethodEnum string + +const ( + ClientSecretPost = "client_secret_post" + ClientSecretBasic = "client_secret_basic" + None = "none" +) diff --git a/lib/management/organization_management_client_test.go b/lib/management/organization_management_client_test.go index e35b20c..2852a83 100644 --- a/lib/management/organization_management_client_test.go +++ b/lib/management/organization_management_client_test.go @@ -30,7 +30,6 @@ func TestClient_ExportAll(t *testing.T) { resp2, _ := client.Detail("60a6f9ad5bcccc51834950c5") log.Printf("%+v\n", resp2) } - func TestClient_GetOrganizationList(t *testing.T) { client := NewClient(userPoolId, appSecret) log.Println("==========获取用户池组织机构列表==========") diff --git a/lib/model/vo_model.go b/lib/model/vo_model.go index 59b8ca1..9391a57 100644 --- a/lib/model/vo_model.go +++ b/lib/model/vo_model.go @@ -82,3 +82,30 @@ type GetRoleUserListRequest struct { Code string `json:"code"` Namespace string `json:"namespace"` } + +type ValidateTokenRequest struct { + AccessToken string `json:"accessToken"` + IdToken string `json:"idToken"` +} + +type ClientCredentialInput struct { + AccessKey string `json:"access_key"` + SecretKey string `json:"secret_key"` +} + +type GetAccessTokenByClientCredentialsRequest struct { + Scope string `json:"scope"` + ClientCredentialInput *ClientCredentialInput `json:"client_credential_input"` +} + +type OidcParams struct { + AppId string + RedirectUri string + ResponseType string + ResponseMode string + State string + Nonce string + Scope string + CodeChallengeMethod string + CodeChallenge string +} diff --git a/lib/util/string_utils.go b/lib/util/string_utils.go new file mode 100644 index 0000000..3fbec7e --- /dev/null +++ b/lib/util/string_utils.go @@ -0,0 +1,28 @@ +package util + +import ( + "github.com/Authing/authing-go-sdk/lib/constant" + "math/rand" +) + +var letters = []rune("abcdefhijkmnprstwxyz2345678") + +func RandomString(length int) string { + b := make([]rune, length) + for i := range b { + b[i] = letters[rand.Intn(len(letters))] + } + return string(b) +} + +func GetValidValue(value ...string) string { + if value == nil || len(value) == 0 { + return constant.StringEmpty + } + for _, val := range value { + if val != "" { + return val + } + } + return constant.StringEmpty +} diff --git a/lib/util/url_utils.go b/lib/util/url_utils.go new file mode 100644 index 0000000..0fe8f48 --- /dev/null +++ b/lib/util/url_utils.go @@ -0,0 +1,20 @@ +package util + +import ( + "github.com/Authing/authing-go-sdk/lib/constant" + "net/url" +) + +func GetQueryString(queryMap map[string]string) string { + if queryMap == nil || len(queryMap) == 0 { + return constant.StringEmpty + } + queryValue := url.Values{} + for key, value := range queryMap { + if value == "" { + continue + } + queryValue.Add(key, value) + } + return queryValue.Encode() +}