Skip to content

x/oauth2: DeviceAuth doesn't populate RetrieveError error codes #75759

@andig

Description

@andig

If this device auth request fails

client_id=xyz&code_challenge=foo&code_challenge_method=S256&scope=authenticate_user+openid

with an error message like this

{"error": "invalid_request", "error_description": "The request is missing a required parameter"}

The returned oauth2.RetrieveError is empty, i.e. does not contain the error message.

This is due to retrieveDeviceAuth missing the error parsing after

if code := r.StatusCode; code < 200 || code > 299 {
	return nil, &RetrieveError{
		Response: r,
		Body:     body,
	}
}

In contrast, regular flow uses internal.doTokenRoundTrip:

switch content {
case "application/x-www-form-urlencoded", "text/plain":
	// some endpoints return a query string
	vals, err := url.ParseQuery(string(body))
	if err != nil {
		if failureStatus {
			return nil, retrieveError
		}
		return nil, fmt.Errorf("oauth2: cannot parse response: %v", err)
	}
	retrieveError.ErrorCode = vals.Get("error")
	retrieveError.ErrorDescription = vals.Get("error_description")
	retrieveError.ErrorURI = vals.Get("error_uri")
	token = &Token{
		AccessToken:  vals.Get("access_token"),
		TokenType:    vals.Get("token_type"),
		RefreshToken: vals.Get("refresh_token"),
		Raw:          vals,
	}
	e := vals.Get("expires_in")
	expires, _ := strconv.Atoi(e)
	if expires != 0 {
		token.Expiry = time.Now().Add(time.Duration(expires) * time.Second)
	}
default:
	var tj tokenJSON
	if err = json.Unmarshal(body, &tj); err != nil {
		if failureStatus {
			return nil, retrieveError
		}
		return nil, fmt.Errorf("oauth2: cannot parse json: %v", err)
	}
	retrieveError.ErrorCode = tj.ErrorCode
	retrieveError.ErrorDescription = tj.ErrorDescription
	retrieveError.ErrorURI = tj.ErrorURI
	token = &Token{
		AccessToken:  tj.AccessToken,
		TokenType:    tj.TokenType,
		RefreshToken: tj.RefreshToken,
		Expiry:       tj.expiry(),
		ExpiresIn:    int64(tj.ExpiresIn),
		Raw:          make(map[string]any),
	}
	json.Unmarshal(body, &token.Raw) // no error checks for optional fields
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugReportIssues describing a possible bug in the Go implementation.Proposal

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions