-
Notifications
You must be signed in to change notification settings - Fork 1
Login with Facebook
Want to build a login system with social account beside with the old email+password way? We can help! Make sure your finish these two articles:
- https://github.com/kidstuff/auth/wiki/Getting-started
- https://github.com/kidstuff/auth/wiki/Integrate-to-your-system
kidstuff/auth already give you the old email+password login, it also give you some help to build your social login on your old, in this article we will try with Facebook OAuth API v2.2 (Google and Twitter work similar, just make sure to read their document).
Here is how it work:
- User choose to login with facebook by click on a link in the front-end and redirected to a FB page.
- At that FB page, FB will ask the user to login (it not yet) an give us the access right for some infomation (email).
- If OK, the page redirect to our front-end site with a code, we send that code to our server.
- If not, you know what to do :D
- The server will use that code to get the FB access token.
- The server will use that FB access token to get user data (email).
- If user with that email already exist, log them in.
- If not, create a new account, email them about that new accoutn, then log them in.
Before we start, go to https://developers.facebook.com and regis a new app with Facebook and set Website URL to http://localhost:8081/ if you're going to test it localy and write out some where you application ID and secret.
The two frist step is pretty simple, you create a link to a special FB page with some special params, here is the link:
https://www.facebook.com/dialog/oauth
?client_id=YOUR_APP_ID
&redirect_uri=http://localhost:8081/facebook_login.html
&response_type=code&scope=email
Reading the document give me that link, when user say OK for our application to access their email, Facebook will redirect the browser to the URI we specific in redirect_uri with an code param appended. (eg: http://localhost:8081/facebook_login.html?code=very-long-random-string).
In the facebook_login.html, your can write a small Ajax function to send a request with that very-long-random-string code to your API server.
Assuming your Go API server will handle that request at localhost:8080/facebook_login
Create a new facebook_login.go in the same folder of the old main.go file.
Edit main.go to route /facebook_login to it handler at facebook_login.go.
main.go
...
r.Handle("/facebook_login", auth.HANDLER_REGISTER(FacebookLogin, false, nil))
...func FacebookLogin(ctx *auth.AuthContext, rw http.ResponseWriter, req *http.Request) (int, error) {
var email string
// here you go to write some code to get user email from Facebbok
// we have it all in the example project, copy it if you too lazy to write your own LoL
status := http.StatusOK
u, err := ctx.Auth.FindUserByEmail(email)
if err == authmodel.ErrNotFound {
// create new user with whatever password,
// this will generate a 24-random-character,
// I think it pretty secure password
pwd := base64.URLEncoding.EncodeToString(securecookie.GenerateRandomKey(16))
u, err = ctx.Auth.AddUser(email, pwd, true)
if err != nil {
return http.StatusInternalServerError, err
}
// the send mail functiuon have soem feature, we will talk about them next article.
err = sendWelcomeMailtoFBUser(ctx, email, pwd)
if err != nil {
ctx.Logs.Errorf("FB user welcome mail failed: %s", err)
status = http.StatusAccepted
}
} else if err != nil {
return http.StatusInternalServerError, err
}
// user already regis with the same email, log them in
tokenStr, err := ctx.Auth.Login(*u.Id, auth.OnlineThreshold)
if err != nil {
return http.StatusInternalServerError, err
}
// You only need to return the token, but the front-end ma keep some user infomation
// for future usage. And this is exactly the same structure our /tokens endpoint use.
inf := struct {
User *authmodel.User
ExpiredOn time.Time
AccessToken string
}{u, time.Now().Add(auth.OnlineThreshold), tokenStr}
return status, json.NewEncoder(rw).Encode(&inf)
}Sure you can ask for use infomation detail on Facebook to copy to you system (with CreateUserDetail)
Go a head and try this with other OAuth provider.