get user info function

This commit is contained in:
kekskurse 2024-09-15 20:42:07 +02:00
parent 38929a7201
commit 7df6d317c9
6 changed files with 109 additions and 4 deletions

45
auth.go
View file

@ -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")

View file

@ -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)
} }

View file

@ -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")
) )

View file

@ -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

View 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"}

View 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"]}