Rails(OAuth)+Android SyncAdapter
今まで書いたAccountManager及びSyncAdapterなやつは認証トークンを適当に作ってそれを利用してAPIにリクエストを投げるという方式だったのですが、そのサーバー側の問題が色々あるのでそこら辺をRailsで組み直し、Android AccountManager+SyncAdapterではOAuthを使ってAPIリクエストを行う方式というのを採用してみた。要は
- アカウント作成時にユーザー・パスワードを入力させてアカウントを作る
- アプリがgetAuthTokenでアクセストークンを要求する際に、アカウントでログインを行いそのアカウントのアクセストークンを取得する
- 取得したアクセストークンを使ってSyncAdapter側でサーバー側とやり取りを行いデータをContent Provider経由でSQLiteに保管する
っていうような手順になる
サーバー側にOAuth Providerの機能を追加
サーバー側はタイトル通りRailsを使用する。で適当にAPIを利用できるようにして、ログイン処理等の機能を実装する。でOAuth Providerな所は https://github.com/applicake/doorkeeper を使用する事でサクッと出来る模様。でdoorkeeperのドキュメント読めば分かるんだけど http://d.hatena.ne.jp/camelmasa/20121005/1349459738 っていう超参考になるのがあるのでそれ読むと良い。とりあえずここであーだらこーだら書くのは避ける
でRails側の http://localhost:3000/oauth/applications にアクセスしてアプリケーション登録を行いClient IDとClient Secretを取得する。でAPI側にはOAuth経由でリクエストされるのを期待させなければならないのでそういうところも盛り込む(doorkeeper_for :allとbefore_filterとか使って)
サーバー側はこんな感じ
Androidアプリ側のAccountManagerにOAuth2のアクセストークン取得処理を実装する
流れ的には
- アカウント作成時に呼ばれるActivityにおいてDialogを表示させてユーザーIDとパスワードを入力させる
- 登録処理が開始したらAccountManager#addAccountExplicitly等を使ってアカウント登録処理を行う
- AbstractAccountAuthenticatorを継承しているクラスにおいて、getAuthTokenメソッドをサーバーからアクセストークンを取得するように実装する。そのトークンをBundleにAccountManager.KEY_AUTHTOKENで返させる。
- そのアクセストークンを使って(ry
な感じかと。でOAuthのアクセストークンを取る方法が
- (GET) http://localhost:3000/oauth/authorize?client_id={Client ID}&redirect_uri={Redirect URI}&response_type=code
- (POST) http://localhost:3000/oauth/token
パラメーターが
- client_id
- client_secret
- code
- grant_Type
- redirect_uri
なパラメーターをセットしてリクエスト。で結果がJSONでアクセストークン・リフレッシュトークン等を含んで出力されるので(ry
な感じな処理をgetAuthTokenに実装する。でアクセストークンに有効期限がある模様だけど、 https://github.com/applicake/doorkeeper/wiki/Customizing-Token-Expiration によると期間を指定出来る模様。なのでサーバーの仕様に合わせてそこら辺をうまくキャッシュしたりすれば良いんじゃないかなーっと
とりあえずフロー的なのうpする
まぁアカウントが無いので作れよーって言われるのでOKを押して独自アカウントを選択すると
というようにユーザーIDとパスワードが要求される。でオッケーを押すとアカウントが作られる。んでアプリに戻る前に
同期を有効にする。でアプリに戻ると
というようにSyncAdapter側でサーバーと通信を行なって取得したデータをContent Providerを通じてSQLiteに保管される
まぁそんな感じ
でやってみて思ったのが結構ややこしい。あとサーバー側のOAuthじゃない所の認証システム辺りが素で自分で組んだんだけど、そこら辺はやはりdeviseとか使って認証システム組んだ方が良さそうな気もする