The following App Engine handler works to the extent that I can obtain a token:
func home(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
oaConfig := map [string]string {
"ClientID": "(redacted)",
"ClientSecret": "(redacted)",
"Scope": "email",
"AuthURL": "https://graph.facebook.com/oauth/authorize",
"TokenURL": "https://graph.facebook.com/oauth/access_token",
"RedirectURL": "http://www.example.com/",
}
code := r.FormValue("code")
if code == "" {
// 1. Code request
url := oaConfig["AuthURL"] +
"?client_id=" + oaConfig["ClientID"] +
"&redirect_uri=" + oaConfig["RedirectURL"] +
"&state=SOME_UNIQUE_VALUE"
http.Redirect(w, r, url, http.StatusFound)
}
// 2. Token request
client := urlfetch.Client(c)
tokenResponse, err := client.PostForm(oaConfig["TokenURL"],
url.Values{
"client_id": {oaConfig["ClientID"]},
"redirect_uri": {oaConfig["RedirectURL"]},
"client_secret": {oaConfig["ClientSecret"]},
"code": {code},
})
if err != nil {
// ...
} else {
// 3. Read token from response body
defer tokenResponse.Body.Close()
body, err := ioutil.ReadAll(tokenResponse.Body)
if err != nil {
// ...
} else {
token := string(body)
}
}
// ...
}
When hooked up to a template, this obtains a token response from Facebook and happily displays it. However, it would be nice not to have to redirect the user to example.com/?state=SOME_UNIQUE_VALUE&code=AQB0iYpAf8nMmX5blahblah#= in order to achieve a login.
Is there a way to use client.Get etc to visit the authorise URL, follow the redirect, obtain the code from the resulting query string and stuff it into a string for use by the handler? Without resorting to Ajax, that is.
No, because the user may have to enter their login credentials to Facebook (and maybe connect to your app too, if they are a first time user) – and that can hardly be done, if you do it all from your server without showing it to the user.
If you want to recognize existing users re-visiting your app when they are already logged in to Facebook – that can only be done client-side.
FB.getLoginStatus
from the JS SDK is able to do that for you – it will recognize the user, and give you a valid access token for them at the same time.