duandi4238 2019-05-10 15:25
浏览 351
已采纳

如何从Google OpenID Connect获取ID_token的示例

I'm trying to get User info from OpenID

https://developers.google.com/identity/protocols/OpenIDConnect#exchangecode

I get a token response from:

tok, err := bookshelf.OAuthConfig.Exchange(context.Background(), code)

I can inspect tok and see there is an id_token element with:

log.Printf("************ tok  contains %#v", tok)

2019/05/13 15:11:24 ************ tok  contains &oauth2.Token{AccessToken:"XXXXXXXXXXX", TokenType:"Bearer", RefreshToken:"", Expiry:time.Time{wall:0xbf2f2c6b181f7b0f, ext:3608126524112, loc:(*time.Location)(0x18516e0)}, raw:map[string]interface {}{"scope":"openid https://www.googleapis.com/auth/profile.emails.read", "token_type":"Bearer", "id_token":"Base64-encodedJSONobject", "access_token":"HASH", "expires_in":3600}}

I don't understand how to extract the Claims from the id_token. Where can I find examples of getting the payload from the JWT id_token?

When I attempted to Decode the id_token

id_token := base64.StdEncoding.DecodeString(tok.id_token)

I get these errors:

multiple-value base64.StdEncoding.DecodeString() in single-value context

/var/folders/mw/0y88j8_54bjc93d_lg3120qw0000gp/T/tmpbPyjTZappengine-go-bin/auth.go:133:49: tok.id_token undefined (type *oauth2.Token has no field or method id_token)

How do I achieve the equivalent of the fetchProfile function below with OpenID instead of Google+?

The only examples I could find use the deprecated Google+ library:

func oauthCallbackHandler(w http.ResponseWriter, r *http.Request) *appError {
    oauthFlowSession, err := bookshelf.SessionStore.Get(r, r.FormValue("state"))
    if err != nil {
        return appErrorf(err, "invalid state parameter. try logging in again.")
    }

    redirectURL, ok := oauthFlowSession.Values[oauthFlowRedirectKey].(string)
    // Validate this callback request came from the app.
    if !ok {
        return appErrorf(err, "invalid state parameter. try logging in again.")
    }

    code := r.FormValue("code")
    tok, err := bookshelf.OAuthConfig.Exchange(context.Background(), code)
    if err != nil {
        return appErrorf(err, "could not get auth token: %v", err)
    }

    session, err := bookshelf.SessionStore.New(r, defaultSessionID)
    if err != nil {
        return appErrorf(err, "could not get default session: %v", err)
    }

    ctx := context.Background()
    profile, err := fetchProfile(ctx, tok)
    if err != nil {
        return appErrorf(err, "could not fetch Google profile: %v", err)
    }

    session.Values[oauthTokenSessionKey] = tok
    // Strip the profile to only the fields we need. Otherwise the struct is too big.
    session.Values[googleProfileSessionKey] = stripProfile(profile)
    if err := session.Save(r, w); err != nil {
        return appErrorf(err, "could not save session: %v", err)
    }

    http.Redirect(w, r, redirectURL, http.StatusFound)
    return nil
}

// fetchProfile retrieves the Google+ profile of the user associated with the
// provided OAuth token.
func fetchProfile(ctx context.Context, tok *oauth2.Token) (*plus.Person, error) {
    client := oauth2.NewClient(ctx, bookshelf.OAuthConfig.TokenSource(ctx, tok))
    plusService, err := plus.New(client)
    if err != nil {
        return nil, err
    }
    return plusService.People.Get("me").Do()
}

It's amazing how many holes there are in the Golang Documentation.

  • 写回答

2条回答 默认 最新

  • douzi9211 2019-05-19 18:20
    关注

    Try this:

    type jwtClaims struct {
        Iss string `json:"iss"`
        Azp string `json:"azp"`
        Aud string `json:"aud"`
        Sub string `json:"sub"`
        Hd string `json:"hd"`
        Email string `json:"email"`
        EmailVerified bool `json:"email_verified"`
        AtHash  string `json:"at_hash"`
        Nonce string `json:"nonce"`
        Iat int `json:"iat"`
        Exp int `json:"exp"`
    }
    
    func extractJwtClaims(token string) (*jwtClaims, error) {
        tokenStruct := &jwtClaims{}
        jwtParts := strings.Split(token, ".")
        out, _ := base64.RawURLEncoding.DecodeString(jwtParts[1])
        err := json.Unmarshal(out, &tokenStruct)
        if err != nil {
            return nil, err
        }
    
        return tokenStruct, nil
    }
    
    func main() {
        token, _ := extractJwtClaims(tok.id_token)
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料
  • ¥15 使用R语言marginaleffects包进行边际效应图绘制
  • ¥20 usb设备兼容性问题
  • ¥15 错误(10048): “调用exui内部功能”库命令的参数“参数4”不能接受空数据。怎么解决啊
  • ¥15 安装svn网络有问题怎么办