Cagrosso
Cagrosso

Reputation: 195

Cookie not being returned with subsequent REST calls to Go Server

I am exploring OAuth2 authentication and set up a server that authenticates with Github. I followed this example, and was able to get it working. I wanted to continue on with some of the suggestions and implement a basic session token system and make the Github calls from my server as opposed to sending the Authorization token to the client.

Here is my slightly modified /oauth/redirect handler

func oauthRedirectHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Println("/oauth/redirect")

    err := r.ParseForm()
    if err != nil {
        fmt.Fprintf(os.Stdout, "could not parse query: %+v", err)
        w.WriteHeader(http.StatusBadRequest)
    }

    code := r.FormValue("code")

    reqURL := fmt.Sprintf("https://github.com/login/oauth/access_token?client_id=%s&client_secret=%s&code=%s", clientID, clientSecret, code)
    req, err := http.NewRequest(http.MethodPost, reqURL, nil)
    if err != nil {
        fmt.Fprintf(os.Stdout, "could not create HTTP request: %v", err)
        w.WriteHeader(http.StatusBadRequest)
    }

    req.Header.Set("accept", "application/json")

    res, err := httpClient.Do(req)
    if err != nil {
        fmt.Fprintf(os.Stdout, "could not send HTTP request: %+v", err)
        w.WriteHeader(http.StatusInternalServerError)
    }
    defer res.Body.Close()

    var t oAuthAccessResponse
    if err := json.NewDecoder(res.Body).Decode(&t); err != nil {
        fmt.Fprintf(os.Stdout, "could not parse JSON response: %+v", err)
        w.WriteHeader(http.StatusBadRequest)
    }

        newSession := sessionTracker{
        AccessToken: accessToken,
        TimeOut:     time.Now().Add(time.Minute * 15),
    }

    sessionToken := uuid.New().String()

    sessionTrackerCache[sessionToken] = newSession

    http.SetCookie(w, &http.Cookie{
        Name:    sessionTokenConst,
        Value:   sessionToken,
        Expires: newSession.TimeOut,
        Domain:  "localhost",
    })

    http.Redirect(w, r, "/welcome.html", http.StatusFound)
}

It redirects to the welcome page with an attached cookie that includes my SessionToken id.

Here is my welcomeHandler

func welcomeHandler(w http.ResponseWriter, req *http.Request) {
    fmt.Println("/welcome")

    cookie, err := req.Cookie(sessionTokenConst)
    if err != nil {
        fmt.Fprintf(os.Stdout, "no cookie attached: %+v", err)
        w.WriteHeader(http.StatusBadRequest)
        return
    } 

    dat, err := ioutil.ReadFile("./public/welcome.html")
    if err != nil {
        fmt.Fprintf(os.Stdout, "could not read welcome page: %+v", err)
        w.WriteHeader(http.StatusInternalServerError)
    }

    fmt.Fprintf(w, string(dat))
}

Observing my browser's network tab, I authenticate with Github and my server is able to see the authorization token. The redirect response at the end of the oauthRedirectHandler contains the cookie with the SessionID. My issue lies in the fact that the browser does not seem to attach the token on the GET call to /welcome.html. I can confirm this in both the browser and in the welcomeHandler.

This is all hosted locally.

I'm not sure if this is a issue with my server, my browser, or if my understanding that cookies are applied by the browser to any future client requests until the cookie expiration date is wrong.

Any help is appreciated!

Upvotes: 1

Views: 791

Answers (1)

Thundercat
Thundercat

Reputation: 120941

Browsers default the cookie path to the request path. Set the path to "/" to make the cookie available across the site.

Do not set the domain unless you specifically have a reason to do so (thank you Volker for noting that).

http.SetCookie(w, &http.Cookie{
    Name:    sessionTokenConst,
    Value:   sessionToken,
    Path:    "/", // <--- add this line
    Expires: newSession.TimeOut,
    // Domain:  "localhost",  <-- Remove this line
})

Upvotes: 4

Related Questions