code: func handleAuthorizationCode(c context.Context, cfg *Settings, code string) (uid string, u *auth.User, err error) {
  	if cfg.ClientID == "" || cfg.ClientSecret == "" || cfg.RedirectURI == "" {
  		return "", nil, ErrNotConfigured
  	}
  
  	// Validate the discover doc has necessary fields to proceed.
  	discovery, err := fetchDiscoveryDoc(c, cfg.DiscoveryURL)
  	switch {
  	case err != nil:
  		return "", nil, err
  	case discovery.TokenEndpoint == "":
  		return "", nil, errors.New("openid: bad discovery doc, empty token_endpoint")
  	}
  
  	// Prepare a request to exchange authorization code for the ID token.
  	v := url.Values{}
  	v.Set("code", code)
  	v.Set("client_id", cfg.ClientID)
  	v.Set("client_secret", cfg.ClientSecret)
  	v.Set("redirect_uri", cfg.RedirectURI)
  	v.Set("grant_type", "authorization_code")
  	payload := v.Encode()
  
  	// Send POST to the token endpoint with URL-encoded parameters to get back the
  	// ID token. There's more stuff in the reply, we don't need it.
  	var token struct {
  		IDToken string `json:"id_token"`
  	}
  	req := internal.Request{
  		Method: "POST",
  		URL:    discovery.TokenEndpoint,
  		Body:   []byte(payload),
  		Headers: map[string]string{
  			"Content-Type": "application/x-www-form-urlencoded",
  		},
  		Out: &token,
  	}
  	if err := req.Do(c); err != nil {
  		return "", nil, err
  	}
  
  	// Unpack the ID token to grab the user information from it.
  	return userFromIDToken(c, token.IDToken, cfg, discovery)
  }
docs: // handleAuthorizationCode exchange `code` for user ID token and user profile.