Я успешно настроил аутентификацию с Auth0, однако, когда Auth0 перенаправляет обратно на мой обратный вызов, я не могу получить доступ к ajax конечным точкам.
Однако, если я обновлю sh страницу (без повторной аутентификации), я теперь могу. Я вижу в localStorage, что access_token
был установлен. Поэтому кажется странным, что при обновлении sh токен установлен, но в первый раз его нет.
Я подозреваю, что загружаю компоненты до установки localStorage, а это означает, что запрос к API завершается неудачно. Однако я не уверен в исправлении.
Я получаю ошибку Error parsing token: Token used before issued
и 401 при запросе к API
Мой код ниже:
Im используя библиотеки
"github.com/auth0/go-jwt-middleware"
"github.com/dgrijalva/jwt-go"
Я инициализирую проверку токена здесь:
func (h *Page) Init() error {
h.JWTMiddleware = jwtmiddleware.New(jwtmiddleware.Options{
ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
aud := os.Getenv("AUTH0_API_AUDIENCE")
checkAudience := token.Claims.(jwt.MapClaims).VerifyAudience(aud, false)
if !checkAudience {
return token, errors.New("Invalid audience.")
}
// verify iss claim
iss := os.Getenv("AUTH0_DOMAIN")
fmt.Println("iss == ", iss)
checkIss := token.Claims.(jwt.MapClaims).VerifyIssuer(iss, false)
if !checkIss {
return token, errors.New("Invalid issuer.")
}
cert, err := getPemCert(token)
if err != nil {
fmt.Println("could not get cert: %+v", err)
return cert, err
}
result, _ := jwt.ParseRSAPublicKeyFromPEM([]byte(cert))
return result, nil
},
SigningMethod: jwt.SigningMethodRS256,
})
return nil
}
Я настраиваю pem и мое промежуточное ПО здесь
func (h *Page) authMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// Get the client secret key
err := h.JWTMiddleware.CheckJWT(c.Writer, c.Request)
if err != nil {
// Token not found
fmt.Println("error checking jwt ", err) <<<---- FAILS HERE!
c.Abort()
c.Writer.WriteHeader(http.StatusUnauthorized)
c.Writer.Write([]byte("Unauthorized"))
return
}
}
}
func getPemCert(token *jwt.Token) (string, error) {
cert := ""
resp, err := http.Get(os.Getenv("AUTH0_DOMAIN") + ".well-known/jwks.json")
if err != nil {
return cert, err
}
defer resp.Body.Close()
var jwks = Jwks{}
err = json.NewDecoder(resp.Body).Decode(&jwks)
if err != nil {
return cert, err
}
x5c := jwks.Keys[0].X5c
for k, v := range x5c {
if token.Header["kid"] == jwks.Keys[k].Kid {
cert = "-----BEGIN CERTIFICATE-----\n" + v + "\n-----END CERTIFICATE-----"
}
}
if cert == "" {
return cert, errors.New("unable to find appropriate key")
}
return cert, nil
}
и мой интерфейс реакции здесь
const AUTH0_CLIENT_ID = "xxx7vOQeStuKmaNfwxoWX"//'{{ $variables := index .Globals "jokish.so"}}{{index $variables "auth0-key"}}';
const AUTH0_DOMAIN = "xxx.eu.auth0.com"//'{{ $variables := index .Globals "jokish.so"}}{{index $variables "domain"}}';
const AUTH0_CALLBACK_URL = "http://localhost:9000/jokes/callback"//'{{ $variables := index .Globals "jokish.so"}}{{index $variables "callback"}}';
const AUTH0_API_AUDIENCE = "https://xxx.eu.auth0.com/api/v2/"//'{{ $variables := index .Globals "jokish.so"}}{{index $variables "audience"}}';
class App extends React.Component {
parseHash() {
this.auth0 = new auth0.WebAuth({
domain: AUTH0_DOMAIN,
clientID: AUTH0_CLIENT_ID
});
this.auth0.parseHash(window.location.hash, (err, authResult) => {
if (err) {
return console.log(err);
}
if (
authResult !== null &&
authResult.accessToken !== null &&
authResult.idToken !== null
) {
localStorage.setItem("access_token", authResult.accessToken);
localStorage.setItem("id_token", authResult.idToken);
localStorage.setItem(
"profile",
JSON.stringify(authResult.idTokenPayload)
);
window.location = window.location.href.substr(
0,
window.location.href.indexOf("#")
);
}
});
}
setup() {
$.ajaxSetup({
beforeSend: (r) => {
console.log("setting ajax up with token ", localStorage.getItem("access_token"))
if (localStorage.getItem("access_token")) {
r.setRequestHeader(
"Authorization",
"Bearer " + localStorage.getItem("access_token")
);
}
}
});
}
setState() {
let idToken = localStorage.getItem("id_token");
if (idToken) {
this.loggedIn = true;
} else {
this.loggedIn = false;
}
}
componentWillMount() {
this.setup();
this.parseHash();
this.setState();
}
render() {
if (this.loggedIn) {
return <LoggedIn />;
}
return <Home />;
}
}
class Home extends React.Component {
constructor(props) {
super(props);
this.authenticate = this.authenticate.bind(this);
}
authenticate() {
this.WebAuth = new auth0.WebAuth({
domain: AUTH0_DOMAIN,
clientID: AUTH0_CLIENT_ID,
scope: "openid profile",
audience: AUTH0_API_AUDIENCE,
responseType: "token id_token",
redirectUri: AUTH0_CALLBACK_URL
});
this.WebAuth.authorize();
}
render() {
return (
<div className="container">
<div className="row">
<div className="col-xs-8 col-xs-offset-2 jumbotron text-center">
<h1>Jokeish</h1>
<p>A load of Dad jokes XD</p>
<p>Sign in to get access </p>
<a
onClick={this.authenticate}
className="btn btn-primary btn-lg btn-login btn-block"
>
Sign In
</a>
</div>
</div>
</div>
);
}
}
class LoggedIn extends React.Component {
constructor(props) {
super(props);
this.state = {
jokes: []
};
this.serverRequest = this.serverRequest.bind(this);
this.logout = this.logout.bind(this);
}
logout() {
localStorage.removeItem("id_token");
localStorage.removeItem("access_token");
localStorage.removeItem("profile");
location.reload();
}
serverRequest() {
$.get("http://localhost:9000/jokes/api/jokes", res => {
this.setState({
jokes: res
});
});
}
componentDidMount() {
this.serverRequest();
}
render() {
return (
<div className="container">
<br />
<span className="pull-right">
<a onClick={this.logout}>Log out</a>
</span>
<h2>Jokeish</h2>
<p>Let's feed you with some funny Jokes!!!</p>
<div className="row">
<div className="container">
{this.state.jokes.map(function(joke, i) {
return <Joke key={i} joke={joke} />;
})}
</div>
</div>
</div>
);
}
}
class Joke extends React.Component {
constructor(props) {
super(props);
this.state = {
liked: "",
jokes: []
};
this.like = this.like.bind(this);
this.serverRequest = this.serverRequest.bind(this);
}
like() {
let joke = this.props.joke;
this.serverRequest(joke);
}
serverRequest(joke) {
$.post(
"http://localhost:9000/jokes/api/jokes/like/" + joke.id,
{ like: 1 },
res => {
console.log("res... ", res);
this.setState({ liked: "Liked!", jokes: res });
this.props.jokes = res;
}
);
}
render() {
return (
<div className="col-xs-4">
<div className="panel panel-default">
<div className="panel-heading">
#{this.props.joke.id}{" "}
<span className="pull-right">{this.state.liked}</span>
</div>
<div className="panel-body joke-hld">{this.props.joke.joke}</div>
<div className="panel-footer">
{this.props.joke.likes} Likes
<a onClick={this.like} className="btn btn-default">
<span className="glyphicon glyphicon-thumbs-up" />
</a>
</div>
</div>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("app"));