Android API Reference
Android API Reference
#Overview
The Magic SDK for Android is your entry-point to secure, passwordless authentication for your mobile app. This guide will cover some important topics for getting started with Android APIs and to make the most of Magic's features.
Magic can support either server-based or serverless web applications. It is up to the developers to implement the Admin SDK to validate the DID Token.
#Getting Started
The Magic
class is the entry-point to the Magic SDK. It must be instantiated with a Magic publishable key. The minimum Android version supported by the Android Magic SDK is version 24.
#Installation
Magic SDK is available in mavenCentral
. Simply add the following to your build.gradle
and settings.gradle
, respectively.
01// build.gradle file
02
03dependencies {
04 implementation 'link.magic:magic-android:9.1.0'
05 implementation 'org.web3j:core:4.8.8-android'
06}
01// settings.gradle file
02
03repositories {
04 mavenCentral()
05}
Sync the project with new dependencies settings.
#Constructor
#Magic()
Parameter | Type | Definition |
|
| Android |
| String | Your publishable API Key retrieved from the Magic Dashboard. |
|
| An enum with values Defaults to Ethereum Mainnet. |
|
| A custom node configuration with the following shape:
|
| String | Customize the language of Magic's modal, email and confirmation screen. See Localization for more. |
#Initialization
01class MagicDemoApp: Application() {
02
03 lateinit var magic: Magic
04
05 override fun onCreate() {
06 magic = Magic(this, "PUBLISHABLE_API_KEY")
07 super.onCreate()
08 }
09}
#Auth Module
The Auth Module and its members are accessible on the Magic SDK instance by the auth
property.
01import link.magic.android.Magic
02
03var magic: Magic
04
05magic.auth;
06magic.auth.loginWithSMS;
07magic.auth.loginWithEmailOTP;
#loginWithSMS
Only available with Dedicated Wallet
Authenticate a user passwordlessly using a one-time code sent to the specified phone number.
List of Currently Blocked Country Codes
#Arguments
context
(Context): Global information about application environmentconfiguration
(LoginWithSMSConfiguration):phoneNumber
(str): The user phone number to log in with
#Returns
DIDToken: Response<String>()
- The function resolves upon authentication request success and rejects with a specific error code if the request fails. The resolved value is a Decentralized ID token with a default 15-minute lifespan.
#Example
01class MagicActivity: AppCompatActivity() {
02
03 lateinit var magic: Magic
04
05 override fun onCreate(savedInstanceState: Bundle?) {
06 super.onCreate(savedInstanceState)
07
08 magic = Magic(this, "PUBLISHABLE_API_KEY")
09 }
10
11 fun login(v: View) {
12 val phoneNumber = findViewById<EditText>(R.id.phone_number_input)
13 val configuration = LoginWithSMSConfiguration(phoneNumber.text.toString())
14 val completable = magic.auth.loginWithSMS(configuration)
15
16 // Logging in
17 completable.whenComplete { response: DIDToken?, error: Throwable? ->
18 if (error != null) {
19 // Handle error
20 }
21 if (response != null && !response.hasError()) {
22 Log.d("Magic", "You're logged in!" + response.result)
23 } else {
24 Log.d("Magic", "Not Logged in")
25 }
26 }
27 }
28}
#loginWithEmailOTP
Only available with Dedicated Wallet
Authenticate a user passwordlessly using an email one-time code sent to the specified user's email address.
#Arguments
context
(Context): Global information about application environmentconfiguration
(LoginWithEmailOTPConfiguration):email
(str): The user email to log in with
#Returns
DIDToken: Response<String>()
- The function resolves upon authentication request success and rejects with a specific error code if the request fails. The resolved value is a Decentralized ID token with a default 15-minute lifespan.
#Example
01class MagicActivity: AppCompatActivity() {
02
03 lateinit var magic: Magic
04
05 override fun onCreate(savedInstanceState: Bundle?) {
06 super.onCreate(savedInstanceState)
07
08 magic = Magic(this, "PUBLISHABLE_API_KEY")
09 }
10
11 fun login(v: View) {
12 val email = findViewById<EditText>(R.id.email_input)
13 val configuration = LoginWithEmailOTPConfiguration(email.text.toString())
14 val completable = magic.auth.loginWithEmailOTP(configuration)
15
16 // Logging in
17 completable.whenComplete { response: DIDToken?, error: Throwable? ->
18 if (error != null) {
19 // Handle error
20 }
21 if (response != null && !response.hasError()) {
22 Log.d("Magic", "You're logged in!" + response.result)
23 } else {
24 Log.d("Magic", "Not Logged in")
25 }
26 }
27 }
28}
#Wallet Module
The Wallet Module and its members are accessible on the Magic SDK instance by the wallet
property.
01import link.magic.android.Magic
02
03var magic: Magic
04
05magic.wallet;
06magic.wallet.connectWithUI;
07magic.wallet.showUI;
08magic.wallet.requestUserInfoWithUI;
#connectWithUI
Renders a simple login form UI to collect the user's email address and authenticate them passwordlessly using a one-time passcode (OTP) sent to their email address they input.
#Arguments
context
(Context): Global information about application environment
#Returns
- A
promiEvent
which returns anString[]
when resolved: An array of user accounts that are connected, with the first element being the current public address of the user. You can read more on PromiEvents here.
#Example
01private fun mcLogin(v: View) {
02 val accounts = (magic as Magic).wallet.connectWithUI(this)
03 accounts.whenComplete { response: ConnectWithUIResponse?, error: Throwable? ->
04 if (error != null) {
05 Log.d("error", error.localizedMessage)
06 }
07 if (response != null && !response.hasError()) {
08 response.result?.let { Log.d("Your Public Address is:", it.first()) }
09 startTabActivity()
10 } else {
11 response?.result?.let { Log.d("Your Public Address is:", it.first()) }
12 Log.i("mcLogin RESPONSE", "Response is: ${response.toString()}")
13 Log.d("MC Login", "Magic Connect Not logged in")
14 }
15 }
16}
#showUI
Displays the fully navigable wallet to the user that adheres to the toggled configurations on your developer dashboard’s Widget UI tab. This is only supported for users who login with email or Google and not third party wallets such as metamask. User must be signed in for this method to return or else it will throw an error.
#Arguments
context
(Context): Global information about application environment
#Returns
Promise
which resolves when the user closes the window
Optionally, add a .on()
handler to catch the disconnect
event emitted when the user logs out from the wallet widget.
#Example
01fun showUI(v: View) {
02 val completable = magic.wallet.showUI(this.requireContext())
03 completable.whenComplete { response: ShowWalletResponse?, error: Throwable? ->
04 if (error != null) {
05 Log.d("error", error.localizedMessage)
06 }
07 if (response != null) {
08 tabActivity.toastAsync("show Wallet:" + response.result)
09 }
10 }
11}
#requestUserInfoWithUI
Displays the wallet widget within an iframe that prompts the user to consent to sharing information with the requesting dApp with OpenID profile scopes. Currently, the only profile scope that can be requested is a verified email. Collecting a verified email address from third-party wallet users (MetaMask, Coinbase Wallet, etc.) is a premium feature but included in the free trial period (see pricing). User must be signed in for this method to return or else it will throw an error.
#Arguments
context
(Context): Global information about application environmentconfiguration
(RequestUserInfoWithUIConfiguration):email
(str): The user email to log in with
#Returns
Promise
which resolves when the user closes the window
#Example
01fun requestUserInfoWithUI(v: View) {
02 val config = RequestUserInfoWithUIConfiguration(
03 scope = WalletUserInfoScope(email = WalletUserInfoEmailOptions.required)
04 )
05 val completable = magic.wallet.requestUserInfoWithUI(this.requireContext(), config)
06 completable.whenComplete { response: RequestUserInfoWithUIResponse?, error: Throwable? ->
07 if (error != null) {
08 Log.d("error", error.localizedMessage)
09 }
10 if (response != null) {
11 tabActivity.toastAsync("Request User Info" + response.result.email)
12 }
13 }
14 }
#User Module
The User Module and its members are accessible on the Magic SDK instance by the user
property.
01import link.magic.android.Magic
02
03var magic: Magic
04
05magic.user
06magic.user.updateEmail
07magic.user.getIdToken
08magic.user.generateIdToken
09magic.user.getMetadata
10magic.user.isLoggedIn
11magic.user.logout
12magic.user.showSettings
13magic.user.updatePhoneNumber
14magic.user.recoverAccount
15magic.user.revealPrivateKey
#updateEmail
Only available with Dedicated Wallet
Initiates the update email flow that allows a user to change to a new email.
#Arguments
context
(Context): Global information about application environment
configuration
(UpdateEmailConfiguration):email
(str): The user email to update withshowUI
(boolean): Iftrue
, show an out-of-the-box pending UI while the request is in flight
#Returns
UpdateEmailResponse: Response<Boolean>()
- TheCompletable
resolves with a true boolean value if update email is successful and rejects with a specific error code if the request fails
#Example
01class MagicActivity: AppCompatActivity() {
02
03 lateinit var magic: Magic
04
05 override fun onCreate(savedInstanceState: Bundle?) {
06 super.onCreate(savedInstanceState)
07
08 magic = Magic(this, "PUBLISHABLE_API_KEY")
09 }
10
11 // Assuming user is logged in
12 fun updateEmail(v: View) {
13
14 val configuration = UpdateEmailConfiguration("new_user_email@example.com")
15 val completable = magic.user.updateEmail(this, configuration)
16 completable.whenComplete { response: UpdateEmailResponse?, error: Throwable? ->
17 if (response != null) {
18 Log.d("Magic", response.result.toString()) // "True"
19 } else {
20 // handle error
21 }
22 }
23 }
24}
#getIdToken
Only available with Dedicated Wallet
Generates a Decentralized Id Token which acts as proof of authentication to resource servers.
#Arguments
context
(Context): Global information about application environmentconfiguration
(GetIdTokenConfiguration):lifespan
(number): will set the lifespan of the generated token. Defaults to 900s (15 mins).
#Returns
PromiEvent<string>
- Base64-encoded string representation of a JSON tuple representing[proof, claim]
01class MagicActivity: AppCompatActivity() {
02 lateinit var magic: Magic
03
04 override fun onCreate(savedInstanceState: Bundle?) {
05 super.onCreate(savedInstanceState)
06
07 magic = Magic(this, "PUBLISHABLE_API_KEY")
08 }
09
10 // Assuming user is logged in
11 fun getIdToken(v: View) {
12 val configuration = GetIdTokenConfiguration(lifespan = 900)
13 val completable = magic.user.getIdToken(configuration)
14 completable.whenComplete { response: GetIdTokenResponse?, error: Throwable? ->
15 if (response != null) {
16 Log.d("Magic", response.result)
17 } else {
18 // handle Error
19 }
20 }
21 }
22}
#generateIdToken
Only available with Dedicated Wallet
Generates a Decentralized Id Token with optional serialized data.
#Arguments
configuration
(GenerateIdTokenConfiguration):lifespan
(number): will set the lifespan of the generated token. Defaults to 900s (15 mins).attachment
(str): will set a signature of serialized data in the generated token. Defaults to"none"
.
#Returns
GenerateIdTokenResponse: Response<String>()
- Base64-encoded string representation of a JSON tuple representing[proof, claim]
#Example
01class MagicActivity: AppCompatActivity() {
02
03 lateinit var magic: Magic
04
05 override fun onCreate(savedInstanceState: Bundle?) {
06 super.onCreate(savedInstanceState)
07
08 magic = Magic(this, "PUBLISHABLE_API_KEY")
09 }
10
11 // Assuming user is logged in
12 fun generateIdToken(v: View) {
13 val configuration = GenerateIdTokenConfiguration(lifespan = 900, attachment = "none")
14 val completable = magic.user.generateIdToken(configuration)
15
16 completable.whenComplete { response: GenerateIdTokenResponse?, error: Throwable? ->
17 if (response != null) {
18 Log.d("Magic", response.result)
19 } else {
20 // handle Error
21 }
22 }
23 }
24}
#getMetadata
Retrieves information for the authenticated user.
#Arguments
- None.
#Returns
GetMetadataResponse: Response<UserMetadataResponse>()
- TheCompletable
containing the issuer, email, phone number, and cryptographic public address of the authenticated user.issuer
(str): The Decentralized ID of the user. In server-side use-cases, we recommend this value to be used as the user ID in your own tables.email
(str): Email address of the authenticated userphoneNumber
(str): Phone number of the authenticated userpublicAddress
(str): The authenticated user's public address (a.k.a.: public key). Currently, this value is associated with the Ethereum blockchain.
#Example
01class MagicActivity: AppCompatActivity() {
02
03 lateinit var magic: Magic
04
05 override fun onCreate(savedInstanceState: Bundle?) {
06 super.onCreate(savedInstanceState)
07
08 magic = Magic(this, "PUBLISHABLE_API_KEY")
09 }
10
11 // Assuming user is logged in
12 fun getMetadata(v: View) {
13 val completable = magic.user.getMetadata()
14 completable.whenComplete { response: GetMetadataResponse?, error: Throwable? ->
15 if (response != null) {
16 Log.d("Magic", "Email: " + response.result.email)
17 Log.d("Magic", "Issuer: " + response.result.issuer)
18 } else {
19 // handle Error
20 }
21 }
22 }
23}
#isLoggedIn
Checks if a user is currently logged in to the Magic SDK.
#Arguments
- None
#Returns
IsLoggedInResponse: Response<Boolean>()
: A boolean value indicating if a user is logged in
#Example
01class MagicActivity: AppCompatActivity() {
02
03 lateinit var magic: Magic
04
05 override fun onCreate(savedInstanceState: Bundle?) {
06 super.onCreate(savedInstanceState)
07
08 magic = Magic(this, "PUBLISHABLE_API_KEY")
09 }
10
11 // Assuming user is logged in
12 fun isLoggedIn(v: View) {
13 val completable = magic.user.isLoggedIn()
14 completable.whenComplete { response: IsLoggedInResponse?, error: Throwable? ->
15 if (response != null && response.result) {
16 Log.d("Magic", "You're Logged In")
17 }
18 if (error != null) {
19 // handle Error
20 }
21 }
22 }
23}
#logout
Logs out the currently authenticated Magic user.
#Arguments
- None
#Returns
LogoutResponse: Response<Boolean>()
: A boolean value indicating if a user has been logged out.
#Example
01class MagicActivity: AppCompatActivity() {
02
03 lateinit var magic: Magic
04
05 override fun onCreate(savedInstanceState: Bundle?) {
06 super.onCreate(savedInstanceState)
07
08 magic = Magic(this, "PUBLISHABLE_API_KEY")
09 }
10
11 // Assuming user is logged in
12 fun logout(v: View) {
13 val completable = magic.user.logout()
14 completable.whenComplete { response: LogoutResponse?, error: Throwable? ->
15 if (response != null && response.result) {
16 Log.d("Magic", "You're logged out!")
17 }
18 if (error != null) {
19 // handle Error
20 }
21 }
22 }
23}
#showSettings
Displays an iframe with the current user’s settings. Allows for users to update their email address, enable multi-factor authentication, and add a recovery factor.
Only available with Dedicated Wallet. Access to MFA and account recovery require paid add-ons.
#Arguments
page?
(String): Optional argument to deeplink to a specific page ('mfa' | 'update-email' | 'recovery'
)
#Returns
Promise
which resolves when the user closes the window
#Example
01class MagicActivity: AppCompatActivity() {
02
03 lateinit var magic: Magic
04
05 override fun onCreate(savedInstanceState: Bundle?) {
06 super.onCreate(savedInstanceState)
07
08 magic = Magic(this, "PUBLISHABLE_API_KEY")
09 }
10
11 // Assuming user is logged in
12 fun showSettings(v: View) {
13 val result = magic.user.showSettings()
14 result.whenComplete { response: GetMetadataResponse?, error: Throwable? ->
15 if (error != null) {
16 Log.d("error", error.localizedMessage)
17 }
18 if (response != null) {
19 tabActivity.toastAsync("Email: " + response.result.email + "\n" + "issuer: " + response.result.issuer + "\n")
20 }
21 }
22 }
23}
#updatePhoneNumber
Initiates the update phone number flow that allows a user to change their phone number.
#Arguments
context
(Context): Global information about application environment
configuration
:phoneNumber
(str): The user phone number to update withshowUI
(boolean): Iftrue
, show an out-of-the-box pending UI while the request is in flight
#Returns
PromiEvent<boolean>
: The promise resolves with a true boolean value if update email is successful and rejects with a specific error code if the request fails
#Example
01fun updateSMS(v: View) {
02 val completable = magic.user.updatePhoneNumber(this.requireActivity())
03 completable.whenComplete { updatePhoneNumberResponse: UpdatePhoneNumberResponse?, error: Throwable? ->
04 if (error != null) {
05 Log.d("error", error.localizedMessage)
06 }
07 if (updatePhoneNumberResponse != null) {
08 Log.d("Update phone number result", updatePhoneNumberResponse.result.toString())
09 }
10 }
11}
#recoverAccount
Initiates the account recovery flow that allows a user to recover their account using their email address.
#Arguments
email
(str): The user email address to recover account with
#Returns
PromiEvent<boolean>
: The promise resolves with a true boolean value if the account recovery is successful and rejects with a specific error code if the request fails
#Example
01private fun recoverAccount(v: View) {
02 val email = findViewById<EditText>(R.id.recovery_email_input)
03 val configuration = RecoverAccountConfiguration(email = email.text.toString())
04 val result = (magic as Magic).user.recoverAccount(this, configuration)
05 result.whenComplete { response: RecoverAccountResponse?, error: Throwable? ->
06 if (error != null) {
07 Log.d("error", error.localizedMessage)
08 }
09 if (response != null) {
10 var result = response.result
11 Log.d("recover account resp result", result.toString())
12 if (result != null) {
13 startTabActivity()
14 } else {
15 toastAsync("RecoverAccount error, consider using a different email")
16 }
17 }
18 }
19}
#revealPrivateKey
Displays an iframe revealing the current user’s private key. Allows for users to take their private key to another wallet. Neither Magic nor the developer can see this key; only the end user can.
#Arguments
- None
#Returns
Promise
which resolves when the user closes the window
#Example
01fun revealPrivateKey(v: View) {
02 val result = magic.user.revealPrivateKey(this.requireContext())
03 result.whenComplete { response: RevealPrivateKeyResponse?, error: Throwable? ->
04 if (error != null) {
05 Log.d("error", error.localizedMessage)
06 }
07 if (response != null) {
08 tabActivity.toastAsync("Key revealed")
09 }
10 }
11}
#OpenID Module
This module requires an enterprise agreement. For more details click here.
The OpenID Module and it's members are accessible on the Magic SDK instance by the openid
property.
To use the OpenID Module in your application, install :magic:ext:oidc
along with magic-android
.
01# In build.gradle
02implementation project(':magic:core')
03implementation project(':magic:ext:oidc')
04
05magic.openid;
06magic.openid.loginWithOIDC;
#loginWithOIDC
Authenticate users via your preferred OIDC client.
Only available with Dedicated Wallet.
#Arguments
jwt
(String): The OIDC token from your identity providerproviderId
(String): An alphanumeric ID provided by Magic after successful configuration of your identity provider
#Returns
PromiEvent<string | null>
: The promise resolves upon authentication request success and rejects with a specific error code if the request fails. The resolved value is a Decentralized ID token with a default 15-minute lifespan.
#Example
01package link.magic.android.extension.oidc.*
02
03magic = Magic(this, '<your_magic_api_key>')
04
05private fun loginWithOIDC(v: View) {
06 val providerId = findViewById<EditText>(R.id.provider_id_text)
07 val jwt = findViewById<EditText>(R.id.jwt_text)
08
09 val configuration = OpenIdConfiguration(jwt.text.toString(),providerId.text.toString())
10
11 val did = magic.openid.loginWithOIDC(this, configuration)
12
13 did.whenComplete { response: DIDToken?, error: Throwable? ->
14 if (error != null) {
15 Log.d("error", error.localizedMessage)
16 }
17
18 if (response != null && !response.hasError()) {
19 response.result?.let { Log.d("login", it) }
20 } else {
21 Log.d("login", "OpenID Not Logged in")
22 }
23 }
24}