Commit 6bc1faf3 authored by Yusuke Iwaki's avatar Yusuke Iwaki

implement Facebook authentication. refactor logic for getting "state" parameter.

parent 88174b75
...@@ -3,6 +3,7 @@ package chat.rocket.android.fragment.oauth; ...@@ -3,6 +3,7 @@ package chat.rocket.android.fragment.oauth;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Base64;
import android.webkit.JavascriptInterface; import android.webkit.JavascriptInterface;
import android.webkit.WebView; import android.webkit.WebView;
import chat.rocket.android.api.MethodCallHelper; import chat.rocket.android.api.MethodCallHelper;
...@@ -11,6 +12,7 @@ import chat.rocket.android.helper.LogcatIfError; ...@@ -11,6 +12,7 @@ import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.model.ServerConfig; import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.model.ddp.MeteorLoginServiceConfiguration; import chat.rocket.android.model.ddp.MeteorLoginServiceConfiguration;
import chat.rocket.android.realm_helper.RealmStore; import chat.rocket.android.realm_helper.RealmStore;
import java.nio.charset.Charset;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import timber.log.Timber; import timber.log.Timber;
...@@ -31,6 +33,18 @@ public abstract class AbstractOAuthFragment extends AbstractWebViewFragment { ...@@ -31,6 +33,18 @@ public abstract class AbstractOAuthFragment extends AbstractWebViewFragment {
&& args.containsKey("serverConfigId"); && args.containsKey("serverConfigId");
} }
protected final String getStateString() {
try {
return Base64.encodeToString(new JSONObject().put("loginStyle", "popup")
.put("credentialToken", getOAuthServiceName() + System.currentTimeMillis())
.put("isCordova", true)
.toString()
.getBytes(Charset.forName("UTF-8")), Base64.NO_WRAP);
} catch (JSONException exception) {
throw new RuntimeException(exception);
}
}
@Override public void onCreate(@Nullable Bundle savedInstanceState) { @Override public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Bundle args = getArguments(); Bundle args = getArguments();
......
package chat.rocket.android.fragment.oauth;
import chat.rocket.android.model.ddp.MeteorLoginServiceConfiguration;
import okhttp3.HttpUrl;
public class FacebookOAuthFragment extends AbstractOAuthFragment {
@Override protected String getOAuthServiceName() {
return "facebook";
}
@Override protected String generateURL(MeteorLoginServiceConfiguration oauthConfig) {
return new HttpUrl.Builder().scheme("https")
.host("www.facebook.com")
.addPathSegment("v2.2")
.addPathSegment("dialog")
.addPathSegment("oauth")
.addQueryParameter("client_id", oauthConfig.getAppId())
.addQueryParameter("redirect_uri", "https://" + hostname + "/_oauth/facebook?close")
.addQueryParameter("display", "popup")
.addQueryParameter("scope", "email")
.addQueryParameter("state", getStateString())
.build()
.toString();
}
}
package chat.rocket.android.fragment.oauth; package chat.rocket.android.fragment.oauth;
import android.util.Base64;
import chat.rocket.android.model.ddp.MeteorLoginServiceConfiguration; import chat.rocket.android.model.ddp.MeteorLoginServiceConfiguration;
import java.nio.charset.Charset;
import okhttp3.HttpUrl; import okhttp3.HttpUrl;
import org.json.JSONObject;
import timber.log.Timber;
public class GitHubOAuthFragment extends AbstractOAuthFragment { public class GitHubOAuthFragment extends AbstractOAuthFragment {
...@@ -14,27 +10,15 @@ public class GitHubOAuthFragment extends AbstractOAuthFragment { ...@@ -14,27 +10,15 @@ public class GitHubOAuthFragment extends AbstractOAuthFragment {
} }
@Override protected String generateURL(MeteorLoginServiceConfiguration oauthConfig) { @Override protected String generateURL(MeteorLoginServiceConfiguration oauthConfig) {
final String clientId = oauthConfig.getClientId();
try {
String state = Base64.encodeToString(new JSONObject().put("loginStyle", "popup")
.put("credentialToken", "github" + System.currentTimeMillis())
.put("isCordova", true)
.toString()
.getBytes(Charset.forName("UTF-8")), Base64.NO_WRAP);
return new HttpUrl.Builder().scheme("https") return new HttpUrl.Builder().scheme("https")
.host("github.com") .host("github.com")
.addPathSegment("login") .addPathSegment("login")
.addPathSegment("oauth") .addPathSegment("oauth")
.addPathSegment("authorize") .addPathSegment("authorize")
.addQueryParameter("client_id", clientId) .addQueryParameter("client_id", oauthConfig.getClientId())
.addQueryParameter("scope", "user:email") .addQueryParameter("scope", "user:email")
.addQueryParameter("state", state) .addQueryParameter("state", getStateString())
.build() .build()
.toString(); .toString();
} catch (Exception exception) {
Timber.e(exception, "failed to generate GitHub OAUth URL");
}
return null;
} }
} }
package chat.rocket.android.fragment.oauth; package chat.rocket.android.fragment.oauth;
import android.util.Base64;
import chat.rocket.android.model.ddp.MeteorLoginServiceConfiguration; import chat.rocket.android.model.ddp.MeteorLoginServiceConfiguration;
import java.nio.charset.Charset;
import okhttp3.HttpUrl; import okhttp3.HttpUrl;
import org.json.JSONObject;
import timber.log.Timber;
public class GoogleOAuthFragment extends AbstractOAuthFragment { public class GoogleOAuthFragment extends AbstractOAuthFragment {
...@@ -14,29 +10,17 @@ public class GoogleOAuthFragment extends AbstractOAuthFragment { ...@@ -14,29 +10,17 @@ public class GoogleOAuthFragment extends AbstractOAuthFragment {
} }
@Override protected String generateURL(MeteorLoginServiceConfiguration oauthConfig) { @Override protected String generateURL(MeteorLoginServiceConfiguration oauthConfig) {
final String clientId = oauthConfig.getClientId();
try {
String state = Base64.encodeToString(new JSONObject().put("loginStyle", "popup")
.put("credentialToken", "google" + System.currentTimeMillis())
.put("isCordova", true)
.toString()
.getBytes(Charset.forName("UTF-8")), Base64.NO_WRAP);
return new HttpUrl.Builder().scheme("https") return new HttpUrl.Builder().scheme("https")
.host("accounts.google.com") .host("accounts.google.com")
.addPathSegment("o") .addPathSegment("o")
.addPathSegment("oauth2") .addPathSegment("oauth2")
.addPathSegment("auth") .addPathSegment("auth")
.addQueryParameter("response_type", "code") .addQueryParameter("response_type", "code")
.addQueryParameter("client_id", clientId) .addQueryParameter("client_id", oauthConfig.getClientId())
.addQueryParameter("scope", "profile email") .addQueryParameter("scope", "profile email")
.addQueryParameter("redirect_uri", "https://" + hostname + "/_oauth/google?close") .addQueryParameter("redirect_uri", "https://" + hostname + "/_oauth/google?close")
.addQueryParameter("state", state) .addQueryParameter("state", getStateString())
.build() .build()
.toString(); .toString();
} catch (Exception exception) {
Timber.e(exception, "failed to generate Google OAUth URL");
}
return null;
} }
} }
package chat.rocket.android.fragment.oauth; package chat.rocket.android.fragment.oauth;
import android.util.Base64;
import chat.rocket.android.model.ddp.MeteorLoginServiceConfiguration; import chat.rocket.android.model.ddp.MeteorLoginServiceConfiguration;
import java.nio.charset.Charset;
import org.json.JSONObject;
import timber.log.Timber;
public class TwitterOAuthFragment extends AbstractOAuthFragment { public class TwitterOAuthFragment extends AbstractOAuthFragment {
...@@ -13,17 +9,7 @@ public class TwitterOAuthFragment extends AbstractOAuthFragment { ...@@ -13,17 +9,7 @@ public class TwitterOAuthFragment extends AbstractOAuthFragment {
} }
@Override protected String generateURL(MeteorLoginServiceConfiguration oauthConfig) { @Override protected String generateURL(MeteorLoginServiceConfiguration oauthConfig) {
try { return "https://" + hostname + "/_oauth/twitter/"
String state = Base64.encodeToString(new JSONObject().put("loginStyle", "popup") + "?requestTokenAndRedirect=true&state=" + getStateString();
.put("credentialToken", "twitter" + System.currentTimeMillis())
.put("isCordova", true)
.toString()
.getBytes(Charset.forName("UTF-8")), Base64.NO_WRAP);
return "https://" + hostname + "/_oauth/twitter/?requestTokenAndRedirect=true&state=" + state;
} catch (Exception exception) {
Timber.e(exception, "failed to generate Twitter OAUth URL");
}
return null;
} }
} }
...@@ -2,6 +2,7 @@ package chat.rocket.android.layouthelper.oauth; ...@@ -2,6 +2,7 @@ package chat.rocket.android.layouthelper.oauth;
import chat.rocket.android.R; import chat.rocket.android.R;
import chat.rocket.android.fragment.oauth.AbstractOAuthFragment; import chat.rocket.android.fragment.oauth.AbstractOAuthFragment;
import chat.rocket.android.fragment.oauth.FacebookOAuthFragment;
import chat.rocket.android.fragment.oauth.GitHubOAuthFragment; import chat.rocket.android.fragment.oauth.GitHubOAuthFragment;
import chat.rocket.android.fragment.oauth.GoogleOAuthFragment; import chat.rocket.android.fragment.oauth.GoogleOAuthFragment;
import chat.rocket.android.fragment.oauth.TwitterOAuthFragment; import chat.rocket.android.fragment.oauth.TwitterOAuthFragment;
...@@ -27,6 +28,8 @@ public class OAuthProviderInfo { ...@@ -27,6 +28,8 @@ public class OAuthProviderInfo {
"github", R.id.btn_login_with_github, GitHubOAuthFragment.class)); "github", R.id.btn_login_with_github, GitHubOAuthFragment.class));
add(new OAuthProviderInfo( add(new OAuthProviderInfo(
"google", R.id.btn_login_with_google, GoogleOAuthFragment.class)); "google", R.id.btn_login_with_google, GoogleOAuthFragment.class));
add(new OAuthProviderInfo(
"facebook", R.id.btn_login_with_facebook, FacebookOAuthFragment.class));
} }
}; };
} }
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
android:id="@+id/btn_login_with_facebook" android:id="@+id/btn_login_with_facebook"
android:layout_width="48dp" android:layout_width="48dp"
android:layout_height="48dp" android:layout_height="48dp"
android:enabled="false"
android:layout_marginEnd="@dimen/margin_8" android:layout_marginEnd="@dimen/margin_8"
android:text="@string/fa_facebook_official" android:text="@string/fa_facebook_official"
android:textSize="16dp" /> android:textSize="16dp" />
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment