github.com/swisscom/cloudfoundry-cli@v7.1.0+incompatible/api/uaa/auth.go (about) 1 package uaa 2 3 import ( 4 "encoding/base64" 5 "encoding/json" 6 "errors" 7 "net/http" 8 "net/url" 9 "strings" 10 11 "code.cloudfoundry.org/cli/api/uaa/constant" 12 "code.cloudfoundry.org/cli/api/uaa/internal" 13 ) 14 15 // AuthResponse contains the access token and refresh token which are granted 16 // after UAA has authorized a user. 17 type AuthResponse struct { 18 AccessToken string `json:"access_token"` 19 RefreshToken string `json:"refresh_token"` 20 } 21 22 // Authenticate sends a username and password to UAA then returns an access 23 // token and a refresh token. 24 func (client Client) Authenticate(creds map[string]string, origin string, grantType constant.GrantType) (string, string, error) { 25 requestBody := url.Values{ 26 "grant_type": {string(grantType)}, 27 } 28 29 for k, v := range creds { 30 requestBody.Set(k, v) 31 } 32 33 type loginHint struct { 34 Origin string `json:"origin"` 35 } 36 37 originStruct := loginHint{origin} 38 originParam, err := json.Marshal(originStruct) 39 if err != nil { 40 return "", "", err 41 } 42 43 var query url.Values 44 if origin != "" { 45 query = url.Values{ 46 "login_hint": {string(originParam)}, 47 } 48 } 49 50 request, err := client.newRequest(requestOptions{ 51 RequestName: internal.PostOAuthTokenRequest, 52 Header: http.Header{ 53 "Content-Type": {"application/x-www-form-urlencoded"}, 54 }, 55 Body: strings.NewReader(requestBody.Encode()), 56 Query: query, 57 }) 58 59 if err != nil { 60 return "", "", err 61 } 62 63 if grantType == constant.GrantTypePassword { 64 request.SetBasicAuth(client.config.UAAOAuthClient(), client.config.UAAOAuthClientSecret()) 65 } 66 67 responseBody := AuthResponse{} 68 response := Response{ 69 Result: &responseBody, 70 } 71 72 err = client.connection.Make(request, &response) 73 return responseBody.AccessToken, responseBody.RefreshToken, err 74 } 75 76 func (client Client) Revoke(token string) error { 77 jti, err := client.getJtiFromToken(token) 78 if err != nil { 79 return err 80 } 81 82 revokeRequest, err := client.newRequest(requestOptions{ 83 RequestName: internal.DeleteTokenRequest, 84 URIParams: map[string]string{ 85 "token_id": jti, 86 }, 87 }) 88 revokeRequest.Header.Set("Authorization", "Bearer "+token) 89 90 if err != nil { 91 return err 92 } 93 94 err = client.connection.Make(revokeRequest, &Response{}) 95 return err 96 } 97 98 func (client Client) getJtiFromToken(token string) (string, error) { 99 segments := strings.Split(token, ".") 100 101 if len(segments) < 2 { 102 return "", errors.New("access token missing segments") 103 } 104 105 jsonPayload, err := base64.RawURLEncoding.DecodeString(segments[1]) 106 107 if err != nil { 108 return "", errors.New("could not base64 decode token payload") 109 } 110 111 payload := make(map[string]interface{}) 112 json.Unmarshal(jsonPayload, &payload) 113 jti, ok := payload["jti"].(string) 114 115 if !ok { 116 return "", errors.New("could not parse jti from payload") 117 } 118 119 return jti, nil 120 }