In your build.gradle
:
dependencies {
implementation 'co.legato.libraries:authentication:latest-version'
}
Social Authentication provides backend services, easy-to-use SDKs, and ready-made UI libraries to authenticate users to your app. It supports authentication using popular federated identity providers like:
- Facebook Authentication
- Google Authentication
- Apple Authentication
- Wechat Authentication
- And more in the fututure as Github, Twitter, Microsoft, Yahoo, Play game sign in...
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Setup configuration for Facebook-->
<string name="facebook_app_id" translatable="false">replace-with-your-id-here</string>
<string name="fb_login_protocol_scheme" translatable="false">replace-with-your-id-here</string>
<string name="facebook_client_token" translatable="false">replace-with-your-id-here</string>
<!-- Setup configuration for Wechat-->
<string name="wechat_app_id" translatable="false" >replace-with-your-id-here</string>
<string name="wechat_secret_id" translatable="false" >replace-with-your-id-here</string>
<!-- No need to configure setting [app_id] for apple and google login. It's already on the file `google-services.json`-->
</resources>
and then refill facebook_app_id
, fb_login_protocol_scheme
with your remote social app.
class FirstFragment : Fragment(), SocialNetworkCallback {
private val binding: FragmentFirstBinding by viewBinding(CreateMethod.INFLATE)
private val manager = AuthenticationManager.getInstance()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
manager.apply {
addNetwork(GoogleNetwork(requireActivity()))
addNetwork(FacebookNetwork(requireActivity(), "email"))
addNetwork(AppleNetwork(requireActivity()))
addNetwork(WechatNetwork(requireActivity()))
}
}
override fun onDestroy() {
super.onDestroy()
manager.reset()
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View = binding.root
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.apple.setOnClickListener {
manager.get<AppleNetwork>(Network.APPLE).login(this)
}
binding.facebook.setOnClickListener {
manager.get<FacebookNetwork>(Network.FACEBOOK).login(this)
}
binding.google.setOnClickListener {
manager.get<GoogleNetwork>(Network.GOOGLE).login(this)
}
binding.wechat.setOnClickListener {
manager.get<WechatNetwork>(Network.WECHAT).login(this)
}
}
override fun onAuthenticationFailed(network: Network, throwable: Throwable?) {
throwable?.printStackTrace()
}
override fun onAuthenticationSuccess(network: Network) {
Toast.makeText(activity, "Authenticated", Toast.LENGTH_SHORT).show()
val token = manager.get<ICoreNetwork>(network).getAccessToken()?.token
Log.e("Authentication", "$network authenticated -> token = $token")
}
override fun onAuthenticationStart() = Unit
}
- Generate signature key: Gradle -> Task -> android -> signingReport. Copy MD5 encoded string, remove colon character and add them in your Wechat Console:
- Create a new directory under your package name wxapi Directory and in the wxapi Add a new one to the directory WXEntryActivity Class, which inherits from the Activity such as the package name of the application.
WXEntryActivity
should be extended from HandlingEventActivity
to catch data from wechat sdk
import vn.cogi.authentication.wxapi.HandlingEventActivity
class WXEntryActivity : HandlingEventActivity()
And in manifest Add the export, taskAffinity, and launchMode attributes to the file, where export is set to true, tasksAfficity to your package name, and launch Mode to singleTask, for example:
<activity
android:name=".wxapi.WXEntryActivity"
android:label="@string/app_name"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:exported="true"
Android: taskAffinity = "fill in your bag name"
android:launchMode="singleTask">
</activity>
We goto Firebase Console --> Authentication -> Settings and tick into Link account that use the same email
:
By default, if FirebaseAuth.getInstance().currentUser
is available. The Authentication
library automatically associates the target provider with the account. In the case of FirebaseAuth.getInstance().currentUser
returns null, the user hasn't been authenticated before, so we have to login with the provider associated with that email address first. Then start linking the target provider to an account. The full sample will be described below:
/**
* A simple [Fragment] subclass as the default destination in the navigation.
*/
class FirstFragment : Fragment(), SocialNetworkCallback {
private val manager = AuthenticationManager.getInstance()
....
override fun onAuthenticationFailed(network: Network, throwable: Throwable?) {
if (throwable is FirebaseAuthUserCollisionException) {
handleFirebaseAuthUserCollisionException(network, throwable)
}
throwable?.printStackTrace()
}
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
private fun handleFirebaseAuthUserCollisionException(
network: Network, throwable: FirebaseAuthUserCollisionException
) {
val credential = throwable.updatedCredential ?: return
val callback = object : SocialNetworkCallback {
override fun onAuthenticationStart() = Unit
override fun onAuthenticationFailed(network: Network, throwable: Throwable?) = Unit
override fun onAuthenticationSuccess(localNetwork: Network) {
Log.e("Authentication", "Target network: $network, Local $localNetwork success")
manager.get<ICoreNetwork>(network).linkWithCredential(credential)
}
}
manager.fetchSignInMethodsForEmail(throwable.email) { providers ->
if (GoogleAuthProvider.PROVIDER_ID in providers) {
// start re-authentication with google provider
manager.get<ICoreNetwork>(Network.GOOGLE).login(callback)
}
}
Log.e("Authentication", "$network failed")
}
override fun onAuthenticationSuccess(network: Network) {
Toast.makeText(activity, "Authenticated", Toast.LENGTH_SHORT).show()
val token = manager.get<ICoreNetwork>(network).getAccessToken()?.token
Log.e("Authentication", "$network authenticated -> token = $token")
}
override fun onAuthenticationStart() = Unit
}