Skip to content

Instantly share code, notes, and snippets.

@misaki0729
Last active December 14, 2015 11:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save misaki0729/0d472985f9de78dd207d to your computer and use it in GitHub Desktop.
Save misaki0729/0d472985f9de78dd207d to your computer and use it in GitHub Desktop.
AndroidでWindowsLiveへの認証をREST APIを利用してやってみる

AndroidでREST APIを使ってWindowsLiveへの認証をしてみる

この記事は 高知工科大 Advent Calendar 2015 の 12/13 の記事です

みなさん、こんちは〜。 12/13の記事を担当するmisaki7247です。

クリスマスまでの日が近づいてきてリア充どもがうきうきしだす時期になりましたが、みなさんいかがお過ごしですか?

記事に何を書くか色々と悩んだんですが、今日やったWindowsLiveの認証についてのことを書いてみようかなーと思います。

なんでやろうと思ったか?

だってOneDriveをAndroidから使いたいのにさー...

Androidで利用する場合、日本語の情報がほぼねーんだもん!

DropboxとかGoogleDriveは割りと日本語の情報があるのにOneDriveがないのはおかしい!

で、WindowsLiveに認証さえすればOneDriveが操作できる!

ってことで書いていきまーす。

あ、OneDrive知らないとか言うそんなあなた。→Google

OneDrive

最終目標

WindowsLiveへの認証の方式にはOAuth2.0が使われてます。 で、この認証方式ではアクセストークンを拾ってくれば認証成功で、私たちの勝ちとなります。

その後はファイルを煮るなり焼くなりすきにできる...ってことで、アクセストークンをぶんどりにいきましょー!

アプリケーション登録

アクセストークンを取得する前に、まずここからアプリケーションの登録をする必要があります。登録方法は簡単なので割愛。

で、登録すればこんな画面が出てきます。

この中でクライアントID、クライアントシークレットが必要になるのでメモっときましょ〜。

Code取得

はい、タイトルの通りですね。 アクセストークンを取得するにはまずCodeという文字列を取得する必要があります。

Codeを取得するには以下のようなURLにアクセスします。

https://login.live.com/oauth20_authorize.srf?
client_id=0000000123ABCD&scope=wl.signin%20wl.basic%20wl.offline_access%20wl.skydrive_update
&response_type=code&redirect_uri=https://login.live.com/oauth20_desktop.srf

この中で必ず変えないといけないのはclient_idの数値です。

scopeに関してはこのページを参考にして必要な物だけを入れましょー。

で、プログラムどうすんの?っていうとこーするの。(プログラム適当なのは急いでやってたから許してT_T )

public class Onedrivetest extends FragmentActivity {

    public static String code = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.onedrive_test);

        Button button = (Button)findViewById(R.id.login);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                openWebView((WebView) findViewById(R.id.wv));
            }
        });
    }

    public String getCode(String url) {
        String code = null;
        String codeKey = "code=";
        int idx = url.indexOf(codeKey);
        if (idx != -1) { // 認証成功ページだった
            code = url.substring(idx + codeKey.length()); // 「code」を切り出し
        }
        return code;
    }

    public void openWebView(WebView wv) {
        wv.getSettings().setJavaScriptEnabled(true);
        wv.setWebViewClient(new WebViewClient() {

            @Override
            public void onPageFinished(WebView view, String url) { // ページ読み込み完了時

                ViewSwitcher vs = (ViewSwitcher)findViewById(R.id.vs);

                // ページurlからコードを取得
                String pageUrl = view.getUrl();
                code = getCode(pageUrl);

                if (code == null) {
                    Log.v("onPageFinished", "コード取得成功ページ以外 url=" + url);
                    if (!(vs.getCurrentView() instanceof WebView)) { // WebViewが表示されてなかったら
                        vs.showNext(); // Web認証画面表示
                    }
                } // コード取得成功
                else {
                    vs.showPrevious(); // 元の画面に戻る
                    Log.v("onPageFinished", "コード取得成功 code=" + code);
                }

            }
        });

        String url = "https://login.live.com/oauth20_authorize.srf?client_id=0000000123ABCDD&scope=wl.signin%20wl.basic%20wl.offline_access%20wl.skydrive_update&response_type=code&redirect_uri=https://login.live.com/oauth20_desktop.srf";
        wv.loadUrl(url);
    }
}

で、レイアウトファイルはこちら。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context="com.promise.t2p.onedrivetest">

    <ViewSwitcher
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/vs">
    	 <Button
        	android:layout_width="wrap_content"
        	android:layout_height="wrap_content"
        	android:text="login"
        	android:id="@+id/login">
        </Button>
        <WebView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/wv">
       </WebView>
    </ViewSwitcher>
</RelativeLayout>

動かしてみるとこんな画面が表示されます。(Manifestでインターネット接続を許可しといてねー。)

サインインするとこんな画面に移ります。

ここで許可するとCodeがページのURLに表示されます。

こんな感じ。

https://login.live.com/oauth20_desktop.srf?
code=123abc456-12ab-1234-1234-1234abcd1234&lc=1043

これを取り出してやれば良いってことで、やり方はソースコード見てねー。

アクセストークン取得

さてみなさん、Codeは取り出せましたね?

ってことで、本題のアクセストークンをぶんどってきましょうー!

で、アクセストークンですが、こんなURLにGETメソッドぶつけます。

https://login.live.com/oauth20_token.srf?client_id=0000000123ABCD
&client_secret=abcdefghzyxwvutsr12345&code=123abc456-12ab-1234-1234-1234abcd1234
&grant_type=authorization_code&redirect_uri=https://login.live.com/oauth20_desktop.srf

すると、こんなJSONが返ってきます。

{
  "token_type": "bearer",
  "expires_in": 3600,
  "scope": "wl.signin wl.basic wl.offline_access wl.skydrive_update",
  "access_token": "a_very_long_access_token_of_hundreds_of_characters",
  "refresh_token": "a_very_long_refresh_token_of_hunderds_of_characters",
  "user_id": "1234567890abcdefghij"
}

ってことで、このJSONを受け取ればあなたは勝ちです...!

ものは試し、やってみよー! ってことで、サンプルコードです。

自分はJSONのデータ持ってくるときにJackson(v2.6.4)、Spring for Android(v1.0.1)使ってるので、このコードはそれを使う場合のみ使用できます。

public class AuthenticationInfo {
    public String token_type;

    public int expires_in; // 有効時間

    public String scope;

    public String access_token;

    public String refresh_token;

    public String user_id;

    public String toString() {
        return "tokenType=" + token_type + "\naccessToken = " + access_token + "\nrefreshToken=" + refresh_token + "\nuserId=" + user_id;
    }
}
public class Onedrivetest extends FragmentActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
		//省略
	     Bundle bundle = new Bundle();
        bundle.putString("format", "json");
        getSupportLoaderManager().initLoader(0, bundle, callbacks);
    }
    
	private LoaderCallbacks<String> callbacks = new LoaderCallbacks<String>() {
        @Override
        public void onLoadFinished(Loader<String> loader, String data) {
            getSupportLoaderManager().destroyLoader(loader.getId());
        }

        @Override
        public void onLoaderReset(Loader<String> loader) {
        }

        @Override
        public Loader<String> onCreateLoader(int id, Bundle args) {
            CustomLoader loader = new CustomLoader(getApplicationContext(), args);
            loader.forceLoad();
            return loader;
        }
    };

    public static class CustomLoader extends AsyncTaskLoader<String> {
        private String mFormat;

        public CustomLoader(Context context, Bundle bundle) {
            super(context);
            mFormat = bundle.getString("format");
        }

        @Override
        public String loadInBackground() {
            return getJson();
        }

        private String getJson() {
            RestTemplate template = new RestTemplate();
            template.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
            String url = 
            "https://login.live.com/oauth20_token.srf?client_id=" + client_id + "&client_secret=" + client_secret + "&code=" + code + "&lc=1041&grant_type=authorization_code&redirect_uri=https://login.live.com/oauth20_desktop.srf";
            try {
                ResponseEntity<AuthenticationInfo> responseEntity = template.exchange(url, HttpMethod.GET, null, AuthenticationInfo.class);
                AuthenticationInfo res = responseEntity.getBody();
                Log.v("でーきたー", res.toString());
                return res.toString();
            } catch (Exception e) {
                Log.d("Error", e.toString());
                return null;
            }
        }
    }
}

あら不思議、これでアクセストークンが取得できちゃうんですね〜。

ちなみに、取得したアクセストークンは800文字を超えてました。

最後に

簡単に認証できるし、みんなやってみよう! サンプルコードはここに上げておいたので気になる人はご自由にどぞー。

ってことで、私が担当の記事は以上となります!

明日の担当はFumiya Kawamuraさんです。 よろしくお願いします!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment