get user info function
This commit is contained in:
parent
38929a7201
commit
7df6d317c9
6 changed files with 109 additions and 4 deletions
45
auth.go
45
auth.go
|
@ -10,6 +10,21 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
Sub string `json:"sub"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuthentikUser struct {
|
||||||
|
User
|
||||||
|
Email string `json:"email"`
|
||||||
|
EmailVerified bool `json:"email_verified"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
GivenName string `json:"given_name"`
|
||||||
|
PreferredUsername string `json:"preferred_username"`
|
||||||
|
Nickname string `json:"nickname"`
|
||||||
|
Groups []string `json:"groups"`
|
||||||
|
}
|
||||||
|
|
||||||
type Auth struct {
|
type Auth struct {
|
||||||
authConfig AuthConfig
|
authConfig AuthConfig
|
||||||
clientConfig ClientConfig
|
clientConfig ClientConfig
|
||||||
|
@ -91,6 +106,36 @@ func (a Auth) GetAuthorizationURL(state string) (string, error) {
|
||||||
return url.String(), nil
|
return url.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a Auth) GetUserInfo(accessToken string, user any) error {
|
||||||
|
req, err := http.NewRequest("GET", a.authConfig.UserinfoEndpoint, nil)
|
||||||
|
|
||||||
|
req.Header.Add("Authorization", "Bearer "+accessToken)
|
||||||
|
|
||||||
|
hc := http.Client{}
|
||||||
|
resp, err := hc.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%w: %q", ErrCreateRequestForUserInfo, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return fmt.Errorf("%w: %s (%v)", ErrCantGetUserInfo, "server response with nuon 200 status code", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%w: %q", ErrCreateRequestForUserInfo, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(body, &user)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%w: %s: %q", ErrCantGetUserInfo, "json unmarshal", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (a Auth) GetTokenFromCode(code string) (Token, error) {
|
func (a Auth) GetTokenFromCode(code string) (Token, error) {
|
||||||
form := url.Values{}
|
form := url.Values{}
|
||||||
form.Add("grant_type", "authorization_code")
|
form.Add("grant_type", "authorization_code")
|
||||||
|
|
59
auth_test.go
59
auth_test.go
|
@ -127,16 +127,67 @@ func TestUseCodeToGetToken(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetUserInfo(t *testing.T) {
|
||||||
|
tts := []struct {
|
||||||
|
name string
|
||||||
|
accessToken string
|
||||||
|
userInfoUrl string
|
||||||
|
exptError error
|
||||||
|
exptErrorMsg string
|
||||||
|
exptUsername string
|
||||||
|
exptNickname string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "token-invalide",
|
||||||
|
accessToken: "abc",
|
||||||
|
userInfoUrl: "http://localhost:8084/userinfo/authentik-success.json",
|
||||||
|
exptUsername: "exampleusername",
|
||||||
|
exptNickname: "mynickname",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "token-invalide",
|
||||||
|
accessToken: "abc",
|
||||||
|
userInfoUrl: "http://localhost:8084/userinfo/authentik-error.json",
|
||||||
|
exptErrorMsg: "cant get user info: server response with nuon 200 status code (400)",
|
||||||
|
exptError: ErrCantGetUserInfo,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tts {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
ClientConfig := ClientConfig{ClientID: "abc", ClientSecret: "def", RedirectURL: "http://localhost/something"}
|
||||||
|
AuthConfig := AuthConfig{UserinfoEndpoint: tt.userInfoUrl}
|
||||||
|
client, err := NewAuthWithConfig(ClientConfig, AuthConfig)
|
||||||
|
assert.Nil(t, err, "should be abel to create client without error")
|
||||||
|
|
||||||
|
u := AuthentikUser{}
|
||||||
|
err = client.GetUserInfo(tt.accessToken, &u)
|
||||||
|
|
||||||
|
assert.ErrorIs(t, err, tt.exptError, "should return right error")
|
||||||
|
|
||||||
|
if tt.exptErrorMsg != "" {
|
||||||
|
assert.Equal(t, tt.exptErrorMsg, err.Error(), "should return right error string")
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, tt.exptUsername, u.PreferredUsername, "should have right user")
|
||||||
|
assert.Equal(t, tt.exptNickname, u.Nickname, "should have right nickname")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestAuthenticLogin(t *testing.T) {
|
func TestAuthenticLogin(t *testing.T) {
|
||||||
t.Skip("dev test")
|
t.Skip("dev")
|
||||||
clientConfig := ClientConfig{ClientID: "abc", ClientSecret: "abc", RedirectURL: "http://localhost/somethingelse"}
|
clientConfig := ClientConfig{ClientID: "hTqEFr0CyS3XVWYC0folnZlU34JdjpRQmjpyhrQR", ClientSecret: "T6CcDWGWMshSLYbRCJ6yfYEphAVUEeeDii9k9o8uECY2ZRPovf2gPiC486W1DSKxIvOcyk2Y0iorBZRO4sbjNEvkfhbMYuEJAKAUk7mD3C7SPAb1MHl79PcZdMn2rdrp", RedirectURL: "http://localhost/somethingelse"}
|
||||||
client, err := NewAuthWithConfigurationURL(clientConfig, "http://localhost:8084/openid-configuration")
|
client, err := NewAuthWithConfigurationURL(clientConfig, "http://localhost:8084/openid-configuration")
|
||||||
assert.Nil(t, err, "should be able to create client without error")
|
assert.Nil(t, err, "should be able to create client without error")
|
||||||
url, err := client.GetAuthorizationURL("")
|
url, err := client.GetAuthorizationURL("")
|
||||||
assert.Nil(t, err, "should be able to create url without error")
|
assert.Nil(t, err, "should be able to create url without error")
|
||||||
fmt.Println(url)
|
fmt.Println(url)
|
||||||
|
|
||||||
token, err := client.GetTokenFromCode("9aa96340040342e5a7df969834d9e278")
|
token, err := client.GetTokenFromCode("0126cbf9d9034fdfbc7b03cff191dc5d")
|
||||||
assert.Nil(t, err, "should be able to get code without error")
|
assert.Nil(t, err, "should be able to get code without error")
|
||||||
fmt.Println(token)
|
fmt.Println(token.AccessToken)
|
||||||
|
|
||||||
|
u := User{}
|
||||||
|
client.GetUserInfo("eyJhbGciOiJSUzI1NiIsImtpZCI6IjQ5ZGRiNmI0YzAxMmEyNjE2NWVhZDY5NTc5YWU1MWE5IiwidHlwIjoiSldUIn0.eyJpc3MiOiJodHRwczovL2F1dGgua2Vrcy5jbG91ZC9hcHBsaWNhdGlvbi9vL3Rlc3QvIiwic3ViIjoiNTE5NGYyZTViNmRlOGEwOTQxODEwM2FkY2ZkYzM0NTMzZjAxYWNjM2Q5YzIwZDM5NzZiNzI1YjE3MmFhMmE0MyIsImF1ZCI6ImhUcUVGcjBDeVMzWFZXWUMwZm9sblpsVTM0SmRqcFJRbWpweWhyUVIiLCJleHAiOjE3MjYzMDY3MjgsImlhdCI6MTcyNjMwNjQyOCwiYXV0aF90aW1lIjoxNzI0NDAzMjczLCJhY3IiOiJnb2F1dGhlbnRpay5pby9wcm92aWRlcnMvb2F1dGgyL2RlZmF1bHQiLCJlbWFpbCI6InNvZXJlbkBzaWVnaXNtdW5kLXBvc2NobWFubi5ldSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJuYW1lIjoiU1x1MDBmNnJlbiIsImdpdmVuX25hbWUiOiJTXHUwMGY2cmVuIiwicHJlZmVycmVkX3VzZXJuYW1lIjoia2Vrc2t1cnNlIiwibmlja25hbWUiOiJrZWtza3Vyc2UiLCJncm91cHMiOlsiYXV0aGVudGlrIEFkbWlucyIsIk5leHRjbG91ZCIsImdpdHVzZXIiLCJnaXRhZG1pbiJdLCJhenAiOiJoVHFFRnIwQ3lTM1hWV1lDMGZvbG5abFUzNEpkanBSUW1qcHloclFSIiwidWlkIjoiazhVUkFXdmpoNnlCSUdIN1JNUWNXZXpVZmF1OWFQRHZGa2tRVXd0SiJ9.il3HHGcVXL260sx1D9D8zvoSF7aIqbBKQVllTs7Giqej_3PBdFID9LQFRt9i0-izTw0M3RVnJ19xLNUZVSXyaRq1CPhuqUxA0fM3DJXfOxesD6pfhW9P92-U8fj_M4VxUwl_XAuWRB_5ynBii5HL4cdia89v4KyY2gohRUoUGvMLMN3qCT1WvS8RPQ--3MsHBi322C2NaPd2QX1TNXnYSaKRT0OQTUDRUopsp7R0KSNppngU813x9oiKL62UxGJ5ZRZ3OPTv0S_rV3Y9Ql9z8nmgcEW5ohckLFiTcb9v1HVr8XoKTU63g0REBkA3ZGh1RNDC99m0P3D_bDqni-fT3rSOOEW2x9gUOjX2SjKv2p4gRU9iHYSO1SCPk68ICTyogtwtHlM7IgGqdwoz10hGijkrOtq6cwWRwWZx6qYRV6TtEwbkEubKeanXOIF_eipUiemc5A-0xFKKC4BTJHrMVXWhKLZoPHYaog8MBMxzm8Hrf4cjfqCfFt1504J2ywUTHERRFr3031QNtICAjOYqrD59KcnCNdU0KztHa0trDfypkk-X_0Cxe0kG2CZX0fc21fQFBLewoTZ1FkOglMu6Yj_Wn7AjtBFQ1dGeWbxi6UJh0B9o2AiSrrOy392D5OTlwvD_Zmy-1c4Ijq5lDd7RbBhEr-pA7Eaz4PagyoAUCnk", &u)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,4 +9,6 @@ var (
|
||||||
ErrCantSendRequestsForToken = errors.New("cant send requests for token with code")
|
ErrCantSendRequestsForToken = errors.New("cant send requests for token with code")
|
||||||
ErrCantGetTokenForCode = errors.New("cant get oauth token with code")
|
ErrCantGetTokenForCode = errors.New("cant get oauth token with code")
|
||||||
ErrWrongResponseFromServer = errors.New("cant get access token from server")
|
ErrWrongResponseFromServer = errors.New("cant get access token from server")
|
||||||
|
ErrCantGetUserInfo = errors.New("cant get user info")
|
||||||
|
ErrCreateRequestForUserInfo = errors.New("cant create request for get user")
|
||||||
)
|
)
|
||||||
|
|
|
@ -10,3 +10,8 @@ routen:
|
||||||
- path: /token/invalide-response
|
- path: /token/invalide-response
|
||||||
response_body: somethings was really wrong
|
response_body: somethings was really wrong
|
||||||
response_http_status: 500
|
response_http_status: 500
|
||||||
|
- path: /userinfo/authentik-error.json
|
||||||
|
response_file: /data/userinfo/authentik-error.json
|
||||||
|
response_http_status: 400
|
||||||
|
- path: /userinfo/authentik-success.json
|
||||||
|
response_file: /data/userinfo/authentik-success.json
|
||||||
|
|
1
minimock/userinfo/authentik-error.json
Normal file
1
minimock/userinfo/authentik-error.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"error": "invalid_grant", "error_description": "The provided authorization grant or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client"}
|
1
minimock/userinfo/authentik-success.json
Normal file
1
minimock/userinfo/authentik-success.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"sub": "5194f2e5b6de8a09418103adcfdc34533f01acc3d2c20d396b725b172aa2a43", "email": "some@eample.com", "email_verified": true, "name": "L\u00f6ren", "given_name": "L\u00f6ren", "preferred_username": "exampleusername", "nickname": "mynickname", "groups": ["authentik Admins", "randomOtherGroupn"]}
|
Loading…
Reference in a new issue