クライアントプロジェクトでは、非常にシンプルな機能を果たしながらトラフィックの多いシンプルなハイブリッドアプリを作成しています。アプリは非常にシンプルであり、Firebaseはプロジェクトの完璧なソリューションのように思えるので、通常はバックエンドは必要ありません。
私が立ち往生している唯一の部分は、SMS Firebaseによる検証/認証です。ただし、いくつかの激しいグーグル検索とドキュメントの読み取りの後、私は簡単な方法はないことに気付きました。これ。これは私がこれまでに見てきたことです:
通常、ハイブリッドモバイルアプリでは、それらの非ネイティブの性質またはJS APIが原因であると考えられますが、初めて(少なくとも私にとっては)そうではないように感じます。この時点で、Firebaseは有効なオプションではないと思いますが、AWSを調べてクライアントのバックエンド全体を設定する前に、コミュニティの愛情と思いやりのあるメンバーに最後に尋ねたいと思いました。
このタイプの認証からミドルサービスを除いて/バックエンドサーバーなしで処理する他の方法はありますか?これらのソリューションを使用した経験はありますか?
更新:2017年5月
電話の認証と認証がFirebaseでネイティブに利用可能になりました。 以下の自己投稿の回答をご覧ください。
更新:2017年4月
Firebaseは、ネイティブで Cloud Functions をサポートするようになりました。これで、サーバーを設定せずにCloud Functionsを使用してこれを実現できます。
更新:2017年10月
Fabric.ioとFirebaseは連携して統合しました Firebase電話認証の桁 で、Fabricの追加機能を開始しました。
2017年5月17日現在、Firebaseのすばらしい人々は、Digitsの電話認証をFirebaseに焼き付けました。 これはFirebase内でネイティブに実現するのが非常に簡単になりました 、スイッチを切り替えるだけで、外部サービスなどを必要とせずに多かれ少なかれ。 ドキュメントで詳細を読むことができます :)
あなたが言及したすべての統合について話すことはできませんが、別のTwilioのサービスであるAuthyを試してみてください。
この種の問題を解決するために、チュートリアルを介して本番用のコードサンプルを最近リリースしました。
そのような例の1つは次のとおりです。
Authy付きの2FAチュートリアル です。次のNode.jsスニペットは、ユーザーステータスが承認または拒否されるのを待機しているエンドポイントを示しています。ユーザーがOneTouchリクエストを承認した場合、セッションをconfirmed
として保存し、正式にログインします。
リクエストが拒否された場合、/verify
ページで、トークンを使用してログインするようユーザーに依頼します。
// Internal endpoint for checking the status of OneTouch
exports.authyStatus = function(request, response) {
var status = (request.user) ? request.user.authyStatus : 'unverified';
if (status == 'approved') {
request.session.confirmed = true;
request.session.save(function(err) {
if (err) return error(response, 500,
'There was an error validating your session.');
});
}
if (!request.session) {
return error(response, 404, 'No valid session found for this user.');
} else {
response.send({ status: status });
}
};
そのため、実際にはサーバーが必要です。しかし、サンプルを試してみると、これはアプリに最適なものを決定するのに役立ちます。
import Android.app.Activity;
import Android.os.Bundle;
import Android.support.annotation.NonNull;
import Android.text.TextUtils;
import Android.util.Log;
import Android.widget.EditText;
import Android.widget.Toast;
import com.google.Android.gms.tasks.OnCompleteListener;
import com.google.Android.gms.tasks.Task;
import com.google.firebase.FirebaseException;
import com.google.firebase.FirebaseTooManyRequestsException;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseAuthInvalidCredentialsException;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.auth.PhoneAuthCredential;
import com.google.firebase.auth.PhoneAuthProvider;
import Java.util.concurrent.TimeUnit;
public class PhoneAutenticationService {
public PhoneAutenticationService(Activity activity,FirebaseAuth auth) {
this.activity = activity;
this.mAuth = auth;
setupCallback();
}
private static final String TAG = PhoneAutenticationService.class.getSimpleName();
private Activity activity;
private String verificationCode;
private static final String KEY_VERIFY_IN_PROGRESS = "key_verify_in_progress";
private static final int STATE_INITIALIZED = 1;
private static final int STATE_CODE_SENT = 2;
private static final int STATE_VERIFY_FAILED = 3;
private static final int STATE_VERIFY_SUCCESS = 4;
private static final int STATE_SIGNIN_FAILED = 5;
private static final int STATE_SIGNIN_SUCCESS = 6;
// [START declare_auth]
private FirebaseAuth mAuth;
// [END declare_auth]
private boolean mVerificationInProgress = false;
private String mVerificationId;
private PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks;
private PhoneAuthProvider.ForceResendingToken mResendToken;
protected void onSaveInstanceState(Bundle outState) {
outState.putBoolean(KEY_VERIFY_IN_PROGRESS, mVerificationInProgress);
}
protected void onRestoreInstanceState(Bundle savedInstanceState) {
mVerificationInProgress = savedInstanceState.getBoolean(KEY_VERIFY_IN_PROGRESS);
}
// [START on_start_check_user]
public void onStart(EditText mPhoneNumberField) {
// Check if user is signed in (non-null) and update UI accordingly.
FirebaseUser currentUser = mAuth.getCurrentUser();
updateUI(currentUser);
// [START_EXCLUDE]
if (mVerificationInProgress && validatePhoneNumber(mPhoneNumberField)) {
startPhoneNumberVerification(mPhoneNumberField.getText().toString());
}
// [END_EXCLUDE]
}
// [END on_start_check_user]
private void setupCallback(){
mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
@Override
public void onVerificationCompleted(PhoneAuthCredential credential) {
// This callback will be invoked in two situations:
// 1 - Instant verification. In some cases the phone number can be instantly
// verified without needing to send or enter a verification code.
// 2 - Auto-retrieval. On some devices Google Play services can automatically
// detect the incoming verification SMS and perform verificaiton without
// user action.
Log.d(TAG, "onVerificationCompleted:" + credential);
// [START_EXCLUDE silent]
mVerificationInProgress = false;
// [END_EXCLUDE]
// [START_EXCLUDE silent]
// Update the UI and attempt sign in with the phone credential
updateUI(STATE_VERIFY_SUCCESS, credential);
// [END_EXCLUDE]
signInWithPhoneAuthCredential(credential);
}
@Override
public void onVerificationFailed(FirebaseException e) {
// This callback is invoked in an invalid request for verification is made,
// for instance if the the phone number format is not valid.
Log.w(TAG, "onVerificationFailed", e);
// [START_EXCLUDE silent]
mVerificationInProgress = false;
// [END_EXCLUDE]
if (e instanceof FirebaseAuthInvalidCredentialsException) {
// Invalid request
// [START_EXCLUDE]
Toast.makeText(activity,"Invalid phone number.",Toast.LENGTH_SHORT).show();
// [END_EXCLUDE]
} else if (e instanceof FirebaseTooManyRequestsException) {
// The SMS quota for the project has been exceeded
// [START_EXCLUDE]
Toast.makeText(activity,"Quota exceeded.",Toast.LENGTH_SHORT).show();
// [END_EXCLUDE]
}
// Show a message and update the UI
// [START_EXCLUDE]
updateUI(STATE_VERIFY_FAILED);
// [END_EXCLUDE]
}
@Override
public void onCodeSent(String verificationId,
PhoneAuthProvider.ForceResendingToken token) {
// The SMS verification code has been sent to the provided phone number, we
// now need to ask the user to enter the code and then construct a credential
// by combining the code with a verification ID.
Log.d(TAG, "onCodeSent:" + verificationId);
Toast.makeText(activity,"onCodeSent:" + verificationId,Toast.LENGTH_SHORT).show();
verificationCode = verificationId;
// Save verification ID and resending token so we can use them later
mVerificationId = verificationId;
setVerificationCode(verificationId);
mResendToken = token;
// [START_EXCLUDE]
// Update UI
updateUI(STATE_CODE_SENT);
// [END_EXCLUDE]
}
};
}
public void startPhoneNumberVerification(String phoneNumber) {
// [START start_phone_auth]
PhoneAuthProvider.getInstance().verifyPhoneNumber(
phoneNumber, // Phone number to verify
60, // Timeout duration
TimeUnit.SECONDS, // Unit of timeout
activity, // Activity (for callback binding)
mCallbacks); // OnVerificationStateChangedCallbacks
// [END start_phone_auth]
mVerificationInProgress = true;
}
public void verifyPhoneNumberWithCode(String verificationId, String code) {
// [START verify_with_code]
PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, code);
// [END verify_with_code]
signInWithPhoneAuthCredential(credential);
}
// [START resend_verification]
public void resendVerificationCode(String phoneNumber,
PhoneAuthProvider.ForceResendingToken token) {
PhoneAuthProvider.getInstance().verifyPhoneNumber(
phoneNumber, // Phone number to verify
60, // Timeout duration
TimeUnit.SECONDS, // Unit of timeout
activity, // Activity (for callback binding)
mCallbacks); // resending
// [END start_phone_auth]
}
// [END resend_verification]
// [START sign_in_with_phone]
public void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
mAuth.signInWithCredential(credential)
.addOnCompleteListener(activity, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// Sign in success, update UI with the signed-in user's information
Log.d(TAG, "signInWithCredential:success");
Toast.makeText(activity,"signInWithCredential:success",Toast.LENGTH_SHORT).show();
FirebaseUser user = task.getResult().getUser();
// [START_EXCLUDE]
updateUI(STATE_SIGNIN_SUCCESS, user);
// [END_EXCLUDE]
} else {
// Sign in failed, display a message and update the UI
Log.w(TAG, "signInWithCredential:failure", task.getException());
if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
// The verification code entered was invalid
// [START_EXCLUDE silent]
Toast.makeText(activity,"Invalid code.",Toast.LENGTH_SHORT).show();
// [END_EXCLUDE]
}
// [START_EXCLUDE silent]
// Update UI
updateUI(STATE_SIGNIN_FAILED);
// [END_EXCLUDE]
}
}
});
}
// [END sign_in_with_phone]
public void signOut() {
mAuth.signOut();
updateUI(STATE_INITIALIZED);
}
private void updateUI(int uiState) {
updateUI(uiState, mAuth.getCurrentUser(), null);
}
public void updateUI(FirebaseUser user) {
if (user != null) {
updateUI(STATE_SIGNIN_SUCCESS, user);
} else {
updateUI(STATE_INITIALIZED);
}
}
private void updateUI(int uiState, FirebaseUser user) {
updateUI(uiState, user, null);
}
private void updateUI(int uiState, PhoneAuthCredential cred) {
updateUI(uiState, null, cred);
}
private void updateUI(int uiState, FirebaseUser user, PhoneAuthCredential cred) {
switch (uiState) {
case STATE_INITIALIZED:
// Initialized state, show only the phone number field and start button
Toast.makeText(activity,"Initialized state",Toast.LENGTH_SHORT).show();
break;
case STATE_CODE_SENT:
// Code sent state, show the verification field, the
Toast.makeText(activity,"Code sent state",Toast.LENGTH_SHORT).show();
break;
case STATE_VERIFY_FAILED:
// Verification has failed, show all options
Toast.makeText(activity,"Verification has failed",Toast.LENGTH_SHORT).show();
break;
case STATE_VERIFY_SUCCESS:
// Verification has succeeded, proceed to firebase sign in
Toast.makeText(activity,"Verification has succeeded",Toast.LENGTH_SHORT).show();
// Set the verification text based on the credential
if (cred != null) {
if (cred.getSmsCode() != null) {
//mVerificationField.setText(cred.getSmsCode());
} else {
Toast.makeText(activity,"Invalid verification code.",Toast.LENGTH_SHORT).show();
}
}
break;
case STATE_SIGNIN_FAILED:
// No-op, handled by sign-in check
Toast.makeText(activity,"Sign in failed",Toast.LENGTH_SHORT).show();
break;
case STATE_SIGNIN_SUCCESS:
// Np-op, handled by sign-in check
Toast.makeText(activity,"Sign in sucesssss!!!!",Toast.LENGTH_SHORT).show();
break;
}
if (user == null) {
// Signed out
} else {
// Signed in
}
}
public boolean validatePhoneNumber(EditText mPhoneNumberField) {
String phoneNumber = mPhoneNumberField.getText().toString();
if (TextUtils.isEmpty(phoneNumber) || phoneNumber.length()>10 || phoneNumber.length()<9) {
Toast.makeText(activity,"Invalid phone number.",Toast.LENGTH_SHORT).show();
return false;
}
return true;
}
public PhoneAuthProvider.OnVerificationStateChangedCallbacks getmCallbacks() {
return mCallbacks;
}
public PhoneAuthProvider.ForceResendingToken getmResendToken() {
return mResendToken;
}
public FirebaseAuth getmAuth() {
return mAuth;
}
public String getVerificationCode() {
return verificationCode;
}
public void setVerificationCode(String verificationCode) {
this.verificationCode = verificationCode;
}
}
アクティビティでFirebaseの認証とリスナーを初期化します
mAuth = FirebaseAuth.getInstance();
mAuthListener = new FirebaseAuth.AuthStateListener() {
@Override
public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
} else {
Log.d(TAG, "onAuthStateChanged:signed_out");
}
// ...
}
};
//init all auth process
phoneAutenticationService = new PhoneAutenticationService(this,mAuth);
@Override
public void onStart() {
super.onStart();
mAuth.addAuthStateListener(mAuthListener);
getActivity().registerReceiver(smsBroadcastReceiver, filter);// define e broadcast receiver to intercept a sms verification code
}
@Override
public void onStop() {
super.onStop();
if (mAuthListener != null) {
mAuth.removeAuthStateListener(mAuthListener);sms code
}
getActivity().unregisterReceiver(smsBroadcastReceiver);
}
そして最後に認証のためにfirebaseメソッドを呼び出します
public void startAuthenticationByPhone(){
if (!validatePhoneNumber(phoneInput)) {
return;
}
startPhoneNumberVerification(phoneInput.getText().toString());
}......
現在、firebaseで電話認証を使用できます。Firebaseを使用した電話認証のコードは次のとおりです。
EditText phoneNum,Code;// two edit text one for enter phone number other for enter OTP code
Button sent_,Verify;// sent button to request for verification and verify is for to verify code
private PhoneAuthProvider.ForceResendingToken mResendToken;
private PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks;
private FirebaseAuth mAuth;
private String mVerificationId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_phone_number_auth);
phoneNum =(EditText) findViewById(R.id.fn_num);
Code =(EditText) findViewById(R.id.code);
sent_ =(Button)findViewById(R.id.sent_nu);
Verify =(Button)findViewById(R.id.verify);
callback_verificvation(); ///function initialization
mAuth = FirebaseAuth.getInstance();
sent_.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String num=phoneNum.getText().toString();
startPhoneNumberVerification(num); // call function for receive OTP 6 digit code
}
});
Verify.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String code=Code.getText().toString();
verifyPhoneNumberWithCode(mVerificationId,code); //call function for verify code
}
});
}
private void startPhoneNumberVerification(String phoneNumber) {
// [START start_phone_auth]
PhoneAuthProvider.getInstance().verifyPhoneNumber(
phoneNumber, // Phone number to verify
60, // Timeout duration
TimeUnit.SECONDS, // Unit of timeout
this, // Activity (for callback binding)
mCallbacks); // OnVerificationStateChangedCallbacks
// [END start_phone_auth]
}
private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// Sign in success, update UI with the signed-in user's information
FirebaseUser user = task.getResult().getUser();
Toast.makeText(getApplicationContext(), "sign in successfull", Toast.LENGTH_SHORT).show();
} else {
// Sign in failed, display a message and update the UI
if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
// The verification code entered was invalid
}
}
}
});
}
private void verifyPhoneNumberWithCode(String verificationId, String code) {
// [START verify_with_code]
PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, code);
// [END verify_with_code]
signInWithPhoneAuthCredential(credential);
}
private void callback_verificvation() {
mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
@Override
public void onVerificationCompleted(PhoneAuthCredential credential) {
// This callback will be invoked in two situations:
// 1 - Instant verification. In some cases the phone number can be instantly
// verified without needing to send or enter a verification code.
// 2 - Auto-retrieval. On some devices Google Play services can automatically
// detect the incoming verification SMS and perform verificaiton without
// user action.
signInWithPhoneAuthCredential(credential);
}
@Override
public void onVerificationFailed(FirebaseException e) {
// This callback is invoked in an invalid request for verification is made,
// for instance if the the phone number format is not valid.
if (e instanceof FirebaseAuthInvalidCredentialsException) {
// Invalid request
} else if (e instanceof FirebaseTooManyRequestsException) {
// The SMS quota for the project has been exceeded
}
// Show a message and update the UI
}
@Override
public void onCodeSent(String verificationId,
PhoneAuthProvider.ForceResendingToken token) {
// The SMS verification code has been sent to the provided phone number, we
// now need to ask the user to enter the code and then construct a credential
// by combining the code with a verification ID.
// Save verification ID and resending token so we can use them later
mVerificationId = verificationId;
mResendToken = token;
}
};