umegusa's blog

備忘録

golangでoauth2を使ってFacebookAPIを叩いてみるよ!!

お前いつもoauth認証やってんな、という突っ込みもお待ちしております。
Facebookは未経験なのもあって結構てこずりました。

revelフレームワークを使ってfacebook認証っぽい何かを実装する

ぶっちゃけ使わなくても全然いけます(確信

いつものようにアプリケーションを作成しましょ。

revel new facebookApp

ルーティングなどは結構適当に作っていいと思います。

TwittweAPIとの違いはFacebookはoauth2を使って認証することです。
oauth2.0のほうが結構楽な気はしてます、毎回面倒な証明書作らなくていいみたいだし。

また、oauth2.0用のライブラリは1.0とは違うライブラリを使います。
golang/oauth2 · GitHub
公式なのかな?
goauth2を使ったやつは結構転がってたんですが、oauth2を使ったやつが全然なかったんですよね。。。

でもgoauth2 is deprecated.とあったのでoauth2を使うしかないような気がしてます。
goauth2 - Go OAuth 2.0 - Google Project Hosting

ということでoauth2を使って認証していくべし!!

認証自体は上記ライブラリを使えばめっちゃ簡単にできます。
ルーティングやらファイル構成は前回の記事を参考にしてみてください。

revelフレームワークを使ってTwitterAPIを叩く! - umegusa's blog

Facebookアプリの登録を行う

下記のサイトからアプリの登録を行います。
Facebook Developers
Developer登録はアカウント認証済みじゃないとだめっぽいので携帯電話の登録とか行いましょう。

作成したらlocalhostでもcallbackできるように設定します。
第一のつまずきポイント。

指定されたURLは、アプリケーションの設定で許可されていません。 
指定されたURLの中にアプリの設定で認められないものが含まれています。
ウェブサイトまたはキャンバスのURLと一致しているか、ドメインがアプリのドメインのサブドメインである必要があります。

登録しないで認証しようとすると上記のように怒られます。
設定はアプリのDashBorad -> Settingsから設定します。f:id:umegusa:20150308233554p:plain
App Domainsにlocalhost, Add PlatformではURLにhttp://localhost/を設定します。
これで、アプリの設定は完了です。

FacebookAPIを叩く!

というわけで実装部分をみてみましょー。
今回は認証を通した人のメールアドレスを取得します。
auth.go

var facebook = newConfig()

func newConfig() *oauth2.Config {
	c := &oauth2.Config{
		ClientID:     "xxxxxxxxxxxxxxxxxxxx",
		ClientSecret: "xxxxxxxxxxxxxxxxxxxx",
		RedirectURL:  "http://localhost:9000/auth/callback",
		Endpoint: oauth2.Endpoint{
			AuthURL:  "https://www.facebook.com/dialog/oauth",
			TokenURL: "https://graph.facebook.com/oauth/access_token",
		},
		Scopes: []string{"email"},
	}

	return c
}

最初にoauth2.Configを定義します。
ClientID,ClientSecretはクライアントアプリのAppID, Secretを指定してください。

んでまずはリクエストトークン(?)を取得しに行きます。

func (c Auth) Index() revel.Result {
	// facebookから情報を取得する
	url := facebook.AuthCodeURL("")
	return c.Redirect(url)
}

AuthCodeURLメソッドを呼ぶとAuthURLで設定したURLが呼び出されます。
んでユーザ認証画面に飛ばされ、RedirecdURLに設定したURLにcallbackされます。

codeパラメータが付加されているので、それを受け取るアクションメソッドも用意します。

func (c Auth) Callback(code string) revel.Result {
	// codeを取得したらユーザ情報を取得

	// アクセストークンを取得
	tok, err := facebook.Exchange(oauth2.NoContext, code)
	// エラー処理は必須
	if err != nil {
		return c.Redirect(App.Index)
	}

	// ユーザ情報を取得
	client := facebook.Client(oauth2.NoContext, tok)
	result, err := client.Get("https://graph.facebook.com/me")
	if err != nil {
		// 失敗
		revel.ERROR.Println("アクセストークン取得失敗!!", err)
	}

	// 関数を抜ける際に必ずresponseをcloseするようにdeferでcloseを呼ぶ
	defer result.Body.Close()

	//jsonをパースする
	account := struct {
		MailAddress string `json:"email"`
	}{}
	_ = json.NewDecoder(result.Body).Decode(&account)

	fmt.Println(account.MailAddress)

	// 取得したhtml(json)を確認する方法
	// byteArray, _ := ioutil.ReadAll(result.Body)
	// fmt.Println(string(byteArray)) // htmlをstringで取得

	return c.Redirect(Show.Index)
}

Exchangeメソッドに帰ってきたコードを渡すことでアクセストークンを取得できます。
TokenURLに設定したURLにcodeパラメータを付加してアクセスしていますね。
err処理を実装しないとエラーでめっちゃ怒られます。
つまずきポイント2でした。

その後はトークンをhttpClientに突っ込んでアクセスすればオッケーです。

あとはencoding/jsonの処理で必要な値のみ取得して終わりです。
さくっとできますね!
途中deferでcloseを呼んでいますが、閉じる必要のあるものは必ず呼び出すようにしましょう。

実行するとアクセスログになんかメールアドレスが表示されているような気がします。

ちなみにFacebookも2.0で習得できるパーミッションの種類が大幅に削減されたみたいです。

  • 公開プロフィール情報)public_profile)
  • メールアドレス(email)
  • いいね!リスト(user_likes
  • 友達リスト(user_friends)

ちなみにこの情報はConfigのScopeに設定する項目になります。
上記を設定することで、使用するユーザにどの権限を使うかを明示的にします。

終わりに

Twitterに比べるとさくっと取れそうな感じですね。
GraphAPI全然勉強してないから何取れるか全然分からないけど
oauth2.0のほうがさくっと取れそうなのでSwiftとかでもチャレンジしてみたいっすね。
最近のサービスはoauth2.0採用してるところが多いので
他のもこんな要領で取れるのではないでしょうか。

今回のソースコードもべしっと。
kaisou4537/revelFacebookApp · GitHub


以上!