【问题标题】:How do I properly authenticate an API call from a React SPA using auth0?如何使用 auth0 正确验证来自 React SPA 的 API 调用?
【发布时间】:2020-04-25 13:00:56
【问题描述】:

我认为这应该相对简单,但我一定遗漏了一些简单的东西。我有一个用户登录到一个单页应用程序,一个在 localhost:3000 上运行的 React 应用程序(使用 yarn start)。

我有一个在 localhost:8080 上运行的后端 API,内置于 go。我想使用 auth0 将我的 API 设为私有。我有前端登录部分工作。我似乎无法正确验证 API 请求。在我的 React 代码中,我有以下内容:

    const auth0 = await createAuth0Client({
        domain: 'mydomain.auth0.com',
        client_id: 'my_client_id_for_react_spa'
    });

    //just making sure this is true. It always is. 
    const isAuthenticated = await auth0.isAuthenticated();

    console.log("Is Authenticated: ", isAuthenticated);

    const token = await auth0.getTokenSilently();

    console.log("Token: ", token);

    try {
        const result = await fetch('http://localhost:8080/api/private', {
            method: 'GET',
            mode: 'no-cors',
            headers: {
                Authorization: 'Bearer ' + token,
            }
        });

        console.log("Result: ", result);
    } catch (e) {
        console.log("Error: ", e);
    }

我收到上述内容的 401 响应。怎么会这样?我已通过身份验证并将令牌与我的请求一起发送。显然我错过了一些东西。

编辑

这里是go代码:

import (
    //...other stuff i need 
    jwtmiddleware "github.com/auth0/go-jwt-middleware"
    "github.com/codegangsta/negroni"
    jwt "github.com/dgrijalva/jwt-go"
    "github.com/gorilla/handlers"
    "github.com/gorilla/mux"
)

r := mux.NewRouter()

jwtMiddleware := jwtmiddleware.New(jwtmiddleware.Options{
    ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {

        // Verify 'aud' claim
        aud := "https://api.mydomain.com"
        checkAud := token.Claims.(jwt.MapClaims).VerifyAudience(aud, false)
        if !checkAud {
            log.Println("Invalid audience")
            return token, errors.New("Invalid audience.")
        }
        // Verify 'iss' claim
        iss := "https://mydomain.auth0.com/"
        checkIss := token.Claims.(jwt.MapClaims).VerifyIssuer(iss, false)
        if !checkIss {
            log.Println("Invalid issuer")
            return token, errors.New("Invalid issuer.")
        }

        cert, err := getPemCert(token)
        if err != nil {
            panic(err.Error())
        }

        result, _ := jwt.ParseRSAPublicKeyFromPEM([]byte(cert))
        return result, nil
    },
    SigningMethod: jwt.SigningMethodRS256,
})

t := testAPIEndpoint{}
n := negroni.New(negroni.HandlerFunc(jwtMiddleware.HandlerWithNext), negroni.Wrap(t))
r.Handle("/api/private", n)

// This route is always accessible
r.Handle("/api/public", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    message := "Hello from a public endpoint! You don't need to be authenticated to see this."
    responseJSON(message, w, http.StatusOK)
}))

allowedOrigins := handlers.AllowedOrigins([]string{"http://localhost:3000"})

log.Fatal(http.ListenAndServe(":8080", handlers.CORS(allowedOrigins)(r)))

【问题讨论】:

  • 发布验证请求的 GO 代码

标签: reactjs go auth0


【解决方案1】:

我认为您在调用 /authorize 端点时没有包含 audience 参数。结果,您收到了不透明的令牌而不是 JWT 令牌。

https://auth0.com/docs/tokens/access-tokens#access-token-structure

试试下面:

  auth0 = await createAuth0Client({
    domain: config.domain,
    client_id: config.clientId,
    audience: config.audience   // API identifier (https://api.mydomain.com)
  });

因此,您将收到带有 API 授权信息的有效 JWT 令牌。尝试解码https://jwt.io 中的令牌以查看令牌结构。确保令牌已获得 aud 声明。 https://auth0.com/docs/tokens/jwt-claims#reserved-claims

我猜你现在可以调用 API 端点了。 https://auth0.com/docs/quickstart/spa/vanillajs/02-calling-an-api#calling-the-api

【讨论】:

  • 谢谢坦弗!这是其中的一部分。我还发现 gorilla mux 中间件拒绝了飞行前的 OPTIONS 请求。我不得不用另一个中间件包装中间件来处理这个 OPTIONS 请求。现在可以了
猜你喜欢
  • 2023-03-21
  • 2018-09-22
  • 1970-01-01
  • 2020-03-17
  • 2018-02-15
  • 1970-01-01
  • 2017-04-01
  • 2017-02-13
  • 1970-01-01
相关资源
最近更新 更多