Firebase令牌记录到我的api

时间:2018-02-08 15:01:38

标签: api firebase go firebase-authentication jwt

我正在为一个网络应用程序和一个Android应用程序制作golang后端。 我使用Firebase进行身份验证。 如果我理解得很好,那么:

  1. 我应该可以在网络应用中进行身份验证
  2. 从谷歌
  3. 获取jwt令牌
  4. authorization: Bearer <jwt>中使用此jwt来拨打我的api
  5. 使用firebase-admin-sdk验证jwt
  6. 如果我错了,有人可以纠正我吗?

    我使用这个html测试页来测试我的认证并记录令牌:

    <html>
    <head>
        <meta charset="UTF-8">
        <title>Sample FirebaseUI App</title>
        <script src="https://cdn.firebase.com/libs/firebaseui/2.5.1/firebaseui.js"></script>
        <link type="text/css" rel="stylesheet" href="https://cdn.firebase.com/libs/firebaseui/2.5.1/firebaseui.css" />
    
        <script src="https://www.gstatic.com/firebasejs/4.9.1/firebase.js"></script>
        <script>
            var config = {
                apiKey: "foo",
                authDomain: "bar.firebaseapp.com",
                databaseURL: "fizz.firebaseio.com",
                projectId: "buzz-193910",
                storageBucket: "john.appspot.com",
                messagingSenderId: "doe"
            };
            firebase.initializeApp(config);
    
            // Initialize the FirebaseUI Widget using Firebase.
            var ui = new firebaseui.auth.AuthUI(firebase.auth());
    
            var uiConfig = {
                callbacks: {
                    signInSuccess: function(currentUser, credential, redirectUrl) {
                        // User successfully signed in.
                        // Return type determines whether we continue the redirect automatically
                        // or whether we leave that to developer to handle.
                        console.log(credential)
                        return true;
                    },
                    uiShown: function() {
                        // The widget is rendered.
                        // Hide the loader.
                        document.getElementById('loader').style.display = 'none';
                    }
                },
                // Will use popup for IDP Providers sign-in flow instead of the default, redirect.
                signInFlow: 'popup',
                signInSuccessUrl: '/test-auth-on-success',
                signInOptions: [
                    // Leave the lines as is for the providers you want to offer your users.
                    firebase.auth.GoogleAuthProvider.PROVIDER_ID,
                    firebase.auth.FacebookAuthProvider.PROVIDER_ID,
                    firebase.auth.TwitterAuthProvider.PROVIDER_ID,
                    firebase.auth.GithubAuthProvider.PROVIDER_ID,
                    firebase.auth.EmailAuthProvider.PROVIDER_ID,
                    firebase.auth.PhoneAuthProvider.PROVIDER_ID
                ],
                // Terms of service url.
                tosUrl: '<your-tos-url>'
            };
    
            ui.start('#firebaseui-auth-container', uiConfig);
    
        </script>
    </head>
    <body>
    <h1>Welcome to My Awesome App</h1>
    <div id="firebaseui-auth-container"></div>
    <div id="loader">Loading...</div>
    </body>
    </html>
    

    这是我用来验证令牌的中间件:

    func (f *Authenticator) Firebase(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
            authorizationHeader := req.Header.Get("authorization")
    
            if authorizationHeader == "" {
                HttpError(w, NewError("invalid authorization token"), http.StatusBadRequest)
                return
            }
    
            bearerToken := strings.Split(authorizationHeader, " ")
            if len(bearerToken) != 2 {
                HttpError(w, NewError("invalid authorization token"), http.StatusBadRequest)
                return
            }
            token, err := f.FirebaseClient.VerifyIDToken(bearerToken[1])
            if err != nil {
                HttpError(w, NewError(fmt.Sprintf("invalid authorization token: %s", err.Error())), http.StatusBadRequest)
                return
            }
    
            [some custom stuff here]
    
            req = req.WithContext(context.WithValue(context.Background(), "decoded", firebaseUser.CustomClaims))
    
            next.ServeHTTP(w, req)
        })
    }
    

    但是,当我从网络日志中使用jwt I ctrl-c / ctrl-v调用我的API时,出现以下错误:failed to verify token signature 我不明白为什么。有什么想法吗?

    [编辑]我向前走了,但还是没有到达终点。我想有些人可能会发现这个主题很有用,所以我会继续告知社区我的进展。

    过了一会儿,我找到了另一个记录api密钥的代码段,我将signInSuccess回调更改为:

    signInSuccess: function(currentUser, credential, redirectUrl) {
        firebase.auth().currentUser.getIdToken(/* forceRefresh */ true).then(function(idToken) {
            console.log(idToken)
            // Send token to your backend via HTTPS
            // ...
        }).catch(function(error) {
            console.log(error)
        });
    
    },
    

    记录正确的令牌。我不是一个前端人,我不明白为什么我可以得到几个jwt,但在这里,它是有效的。现在我收到以下错误:ID token issued at future timestamp: 1518108929

1 个答案:

答案 0 :(得分:3)

好的,我成功了。

错误1:无法验证令牌签名

所以,回顾一下:我的html测试页面没有记录正确的令牌。好的代码如下:

signInSuccess: function(currentUser, credential, redirectUrl) {
    firebase.auth().currentUser.getIdToken(/* forceRefresh */ true).then(function(idToken) {
        console.log(idToken)
        // Send token to your backend via HTTPS
        // ...
    }).catch(function(error) {
        console.log(error)
    });

},

错误2:在未来时间戳

发出的ID令牌

我的电脑时钟与mondial时间不完全同步。这是愚蠢的。