1

I am working on a Golang Api based on Gin Framework , this Api has a method of authentication using jwt (json web tokens)

i have the frontend client which is written in javascript (ajax,jquery)

i have to do a login with a POST method it generates me the token based on the email and the password from the inputs in front end ,

This is working perfectly in postman with login endpoints and get after to the hello endpoints(private endpoints) but in the browser it gives me an error.

The error is :Response for preflight has invalid HTTP status code 401

This error i got it just from the browser (Chrome) , but it is working at Postman

i have fixed the problem for CORS by adding an extention in the browser but it is not working by giving me the error

Could you please help here?? , thanks indeed for any help or suggestions.

Here is the client side :

<html>
<link rel="stylesheet" href="test.css">
<body>
    <form id ="form"  method="POST">
        <p>Email:</p><br>
        <input type="text" id="email" placeholder="body" /><br>
        <p>Password:</p><br>
        <input type="text" id="password" placeholder="body" />
        <br>
        <input  type="submit" value="Submit">
    </form>

    <script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
    <script type="text/javascript">
    var username;
    var password;

    $("#form").submit(function(e) {
        var url = "http://localhost:1234/login"; 
        var url1= "http://localhost:1234/v1/hello";
        var data;// the script where you handle the form input.
        var jwttoken;
        username=$('#username').val();
        password=$('#password').val();

        $.ajax({
            type: "POST",
            url: url,
            data: JSON.stringify({ 
                // Those property names must match the property names of your PromotionDecision  view model
                username:username,
                password: password}),
                success: function(data)
                {

                    console.log(data); 
                    window.localStorage.setItem('token', data.token);
                    console.log(window.localStorage.getItem('token'));

                    $.ajax({
                        type: "GET",
                        beforeSend: function (request)
                        {
                            request.withCredentials = true;
                            request.setRequestHeader("Authorization", "Bearer " +  "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1Mjc4NTcyOTEsImlkIjoiZWxtZWhkaS5hYXJhYkBzY2hpYnN0ZWQuY29tIiwib3JpZ19pYXQiOjE1Mjc4NTM2OTEsInJvbGUiOiJhZG1pbiJ9.wS3trHKUChsU-OmSo6tDUPPuzVriJF7z9i0_8W_36nY");
                        },
                        url: url1,
                        success: function(datad)
                        {
                            console.log(datad); 
                        }
                    });
                }
        });
        e.preventDefault(); // avoid to execute the actual submit of the form.
    });
    </script>
</body>
</html>

Here is the api GOLANG (Gin framework) using JWT:

package main

import (
    "fmt"
    "github.com/gin-gonic/gin"
    jwt "gopkg.in/appleboy/gin-jwt.v2"
    "net/http"
    "time"
)

func main() {
    router := gin.Default()

    jwtMiddleware := &jwt.GinJWTMiddleware{
        Realm: "user.io",

        Key:           []byte("changeme"),
        Timeout:       time.Hour,
        MaxRefresh:    time.Hour,
        Authenticator: authenticate,

        PayloadFunc: payload,
    }

    router.POST("/login", jwtMiddleware.LoginHandler)
    router.OPTIONS("/login", jwtMiddleware.LoginHandler)

    v1 := router.Group("/v1")

    v1.Use(jwtMiddleware.MiddlewareFunc())
    {
        v1.GET("/hello", hello)
        v1.OPTIONS("/hello", hello)

    }
    router.Run(":1234")
}

func hello(c *gin.Context) {
    fmt.Println("hello", c.Request.Header["Authorization"])

    claims := jwt.ExtractClaims(c)
    c.String(http.StatusOK, "id: %s\nrole: %s\n", claims["id"], claims["role"])
}

func authenticate(email string, password string, c *gin.Context) (string, bool) {
    if email == "mike@gmail.com" && password == "med" {
        return email, true
    }
    return "", false
}

func payload(email string) map[string]interface{} {
    return map[string]interface{}{
        "id":   "1349",
        "role": "admin",
    }
}
Medo
  • 55
  • 8
  • 1
    Try with space between "Bearer" and the token itself. – mkopriva Jun 01 '18 at 14:32
  • @mkopriva the same issue after making a space , i found a problem in stack ["The same issue"](https://stackoverflow.com/questions/29954037/why-is-an-options-request-sent-and-can-i-disable-it) to add `Access-Control-Allow-Origin: *` but i can't figure out where i have to add it – Medo Jun 01 '18 at 14:50
  • If you search for "gin cors middleware" I'm fairly certain you'll find some contrib package to do this for you. You would then pass the middleware to `Use` just like you're passing the `jwtMiddleware.MiddlewareFunc()`. – mkopriva Jun 01 '18 at 14:53
  • 1
    first result from google https://github.com/gin-contrib/cors. – mkopriva Jun 01 '18 at 14:55
  • so basically it is a backend issue not a front end @mkopriva? – Medo Jun 01 '18 at 14:59
  • I don't know, you've decided that it is a CORS issue but the error you've provided does not look like a CORS problem to me. – mkopriva Jun 01 '18 at 15:01
  • Also in your code example you've hardcoded some random token (`"eyJhbGciOiJIUzI1NiIsI..."`) for the GET request instead of using the returned `data.token` from the POST response. – mkopriva Jun 01 '18 at 15:03
  • what do you suggest that could be ? i mentioned in the problem with strong font that i installed an extension for CORS , thanks for the help by the way – Medo Jun 01 '18 at 15:04
  • @mkopriva the purpose of that i made the token to be expired by an hour so i hardcoded the token , but even though i was getting the same issue when i set `data.token` i am a little bit confusing , this is my first time working with `jwt go ` – Medo Jun 01 '18 at 15:06
  • CORS error messages usually look something like this: `... cannot load http://. No 'Access-Control-Allow-Origin' header is present on the requested resource. ...`. If you're getting a message like this, then you have a CORS problem, if not then it's highly probable that it's not a CORS problem. – mkopriva Jun 01 '18 at 15:11
  • You also say you've installed an extension for CORS but in your Go code there is no such indication, no middleware, no nothing... Where and how exactly did you install that extension? – mkopriva Jun 01 '18 at 15:16
  • Another thing that seems off is the explicit handling of OPTIONS methods. In most cases the OPTIONS requests should be handled by the CORS middleware and not by normal handlers. – mkopriva Jun 01 '18 at 15:25
  • @mkopriva i have done it in the browser (Google chrome ) the extention name `moesif cros` – Medo Jun 01 '18 at 15:25
  • i added the method `OPTIONS` because i was getting an error `bad request 400`while doing the `POST` with `the login endpoint` – Medo Jun 01 '18 at 15:26
  • Well it doesn't seem to me like you're handling the OPTIONS request correctly. Just add the proper CORS middleware to your Go app, it will handle the OPTIONS for you and you should be able to turn off the extension as well. – mkopriva Jun 01 '18 at 15:30
  • @mkopriva i am working on it , but please do you have an idea how to make an authenticator (email,password) from front end request are verified to generate the token ? because in this example (server side) there is a value called ` Authenticator: authenticate` and `authenticate is a function testing the username and password`? thanks indeed for any suggestions – Medo Jun 01 '18 at 15:39

0 Answers0