Golang : Login(Authenticate) with Facebook example
By today's Internet standard, if you want to create a website or app that allows user to login, it won't be complete without a Facebook login button.
In this tutorial, we will explore how to :
- generate a Facebook Login URL string and bind a "Login with Facebook" button to the URL.
- generate access token from the returned
code
after login successfully. - dump out all the data returned by Facebook (depending on the scope - email, userbirthday, userlocation, useraboutme).
- get some data such as id, birthday, username and profile photo.
Please take note that, this tutorial uses couple of third party packages :
"github.com/golang/oauth2"
"github.com/antonholmquist/jason"
NOTE : Because I've executed this code in one of my Digital Ocean's droplet with an IP-address instead of domain name. I need to "fool" the Facebook Developers App Setting by setting the Mobile Site URL
to http://<ip address>:8080/
at https://developers.facebook.com/apps/<app id>/settings/
. You don't have to do this if you are executing the code in the domain name specified in the Facebook App Site URL
setting.
NOTE : This tutorial assumes that you've setup your Facebook App and already have the AppID and Secret.
Here you go :
package main
import (
"fmt"
"github.com/antonholmquist/jason"
"github.com/golang/oauth2"
"net/http"
"strconv"
"strings"
)
type AccessToken struct {
Token string
Expiry int64
}
func readHttpBody(response *http.Response) string {
fmt.Println("Reading body")
bodyBuffer := make([]byte, 5000)
var str string
count, err := response.Body.Read(bodyBuffer)
for ; count > 0; count, err = response.Body.Read(bodyBuffer) {
if err != nil {
}
str += string(bodyBuffer[:count])
}
return str
}
//Converts a code to an Auth_Token
func GetAccessToken(client_id string, code string, secret string, callbackUri string) AccessToken {
fmt.Println("GetAccessToken")
//https://graph.facebook.com/oauth/access_token?client_id=YOUR_APP_ID&redirect_uri=YOUR_REDIRECT_URI&client_secret=YOUR_APP_SECRET&code=CODE_GENERATED_BY_FACEBOOK
response, err := http.Get("https://graph.facebook.com/oauth/access_token?client_id=" +
client_id + "&redirect_uri=" + callbackUri +
"&client_secret=" + secret + "&code=" + code)
if err == nil {
auth := readHttpBody(response)
var token AccessToken
tokenArr := strings.Split(auth, "&")
token.Token = strings.Split(tokenArr[0], "=")[1]
expireInt, err := strconv.Atoi(strings.Split(tokenArr[1], "=")[1])
if err == nil {
token.Expiry = int64(expireInt)
}
return token
}
var token AccessToken
return token
}
func Home(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
// generate loginURL
fbConfig := &oauth2.Config{
// ClientId: FBAppID(string), ClientSecret : FBSecret(string)
// Example - ClientId: "1234567890", ClientSecret: "red2drdff6e2321e51aedcc94e19c76ee"
ClientID: "", // change this to yours
ClientSecret: "",
RedirectURL: "http://<domain name and don't forget port number if you use one>/FBLogin", // change this to your webserver adddress
Scopes: []string{"email", "user_birthday", "user_location", "user_about_me"},
Endpoint: oauth2.Endpoint{
AuthURL: "https://www.facebook.com/dialog/oauth",
TokenURL: "https://graph.facebook.com/oauth/access_token",
},
}
url := fbConfig.AuthCodeURL("")
// Home page will display a button for login to Facebook
w.Write([]byte("<html><title>Golang Login Facebook Example</title> <body> <a href='" + url + "'><button>Login with Facebook!</button> </a> </body></html>"))
}
func FBLogin(w http.ResponseWriter, r *http.Request) {
// grab the code fragment
w.Header().Set("Content-Type", "text/html; charset=utf-8")
code := r.FormValue("code")
ClientId := "" // change this to yours
ClientSecret := ""
RedirectURL := "http://<domain name and don't forget port number if you use one>/FBLogin"
accessToken := GetAccessToken(ClientId, code, ClientSecret, RedirectURL)
response, err := http.Get("https://graph.facebook.com/me?access_token=" + accessToken.Token)
// handle err. You need to change this into something more robust
// such as redirect back to home page with error message
if err != nil {
w.Write([]byte(err.Error()))
}
str := readHttpBody(response)
// dump out all the data
// w.Write([]byte(str))
// see https://www.socketloop.com/tutorials/golang-process-json-data-with-jason-package
user, _ := jason.NewObjectFromBytes([]byte(str))
id, _ := user.GetString("id")
email, _ := user.GetString("email")
bday, _ := user.GetString("birthday")
fbusername, _ := user.GetString("username")
w.Write([]byte(fmt.Sprintf("Username %s ID is %s and birthday is %s and email is %s<br>", fbusername, id, bday, email)))
img := "https://graph.facebook.com/" + id + "/picture?width=180&height=180"
w.Write([]byte("Photo is located at " + img + "<br>"))
// see https://www.socketloop.com/tutorials/golang-download-file-example on how to save FB file to disk
w.Write([]byte("<img src='" + img + "'>"))
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", Home)
mux.HandleFunc("/FBLogin", FBLogin)
http.ListenAndServe(":8080", mux)
}
Output :
References :
By Adam Ng
IF you gain some knowledge or the information here solved your programming problem. Please consider donating to the less fortunate or some charities that you like. Apart from donation, planting trees, volunteering or reducing your carbon footprint will be great too.
Advertisement
Tutorials
+21.8k Golang : GORM create record or insert new record into database example
+5.2k Linux : How to set root password in Linux Mint
+19k Golang : How to make function callback or pass value from function as parameter?
+10.7k Golang : Generate 403 Forbidden to protect a page or prevent indexing by search engine
+11.4k Golang : How to pipe input data to executing child process?
+5.4k Golang : Generate Interleaved 2 inch by 5 inch barcode
+12.4k Golang : List running EC2 instances and descriptions
+7.4k Golang : Check if one string(rune) is permutation of another string(rune)
+16.5k Golang : How to implement two-factor authentication?
+10.1k Golang : Setting variable value with ldflags
+7k Golang : Normalize email to prevent multiple signups example
+7.9k Golang : Getting Echo framework StartAutoTLS to work