Skip to content

Instantly share code, notes, and snippets.

@mattlockyer
Last active June 19, 2019 00:01
Show Gist options
  • Save mattlockyer/9dbbed5f50a9c972e664b4ed81235ab5 to your computer and use it in GitHub Desktop.
Save mattlockyer/9dbbed5f50a9c972e664b4ed81235ab5 to your computer and use it in GitHub Desktop.
Facebook Login for Web with Using Go Server. Token returned from FB Login button on client. Client makes POST request. FB API called with GET request. Token Validated. Reponsd to client with error / JSON.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Facebook Login Example</title>
<meta name="description" content="Facebook Login Example">
<meta name="author" content="Matt Lockyer">
</head>
<body>
<div class="fb-login-button" data-width="" data-size="large" data-button-type="continue_with" data-auto-logout-link="false" data-use-continue-as="false"></div>
<div id="fb-root"></div>
<script crossorigin="anonymous" src="https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v3.3&appId=xxxxxxxxxxxxxxx&autoLogAppEvents=1"></script>
<script>
window.onload = () => {
FB.getLoginStatus(async (response) => {
if (response.status === 'connected') {
const token = response.authResponse.accessToken
console.log(token)
const res = await fetch('http://localhost:8080/validate', {
method: 'POST', mode: "cors",
body: JSON.stringify({ token })
}).then((res) => res.json())
console.log(res)
}
})
}
</script>
</body>
</html>
package main
import (
"encoding/json"
"net/http"
)
/********************************
Accept TokenPayload from the client with only token field provided
Validate client token with fb api
Repond with TokenPayload fully or partially filled
********************************/
var access_token string = "xxxxxxxxxxxxxxx|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
type TokenPayload struct {
UserId string `json:"user_id"`
Token string `json:"token"`
Message string `json:"message"`
}
type msi = map[string]interface{}
func validate(w http.ResponseWriter, r *http.Request) {
// Read body
defer r.Body.Close()
// Unmarshal
var payload TokenPayload
err := json.NewDecoder(r.Body).Decode(&payload)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
// Fetch response for payload.Token
r2, err := http.Get("https://graph.facebook.com/v3.3/debug_token?input_token=" +
payload.Token + "&access_token=" + access_token)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
defer r2.Body.Close()
var r3 msi
err = json.NewDecoder(r2.Body).Decode(&r3)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
// FB error will respond with object { "error": ... } and the below will panic
if r3["error"] != nil {
http.Error(w, err.Error(), 500)
return
}
fbData := r3["data"].(msi)
if (!fbData["is_valid"].(bool)) {
payload.Message = "FB token not valid"
} else {
payload.Message = "FB token is valid"
payload.UserId = fbData["user_id"].(string)
}
// Return output
output, err := json.Marshal(payload)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
w.Header().Set("content-type", "application/json")
w.Write(output)
}
func index(w http.ResponseWriter, r *http.Request) {
}
func main() {
http.Handle("/", http.FileServer(http.Dir("./static")))
http.HandleFunc("/validate", validate)
println("Listening on 8080")
http.ListenAndServe(":8080", nil)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment