0 purchases
cotter
cotter #
A Flutter SDK for Cotter's Authentication Services. This package helps you add passwordless login to your app using the following methods:
✅ Sign in with device
✅ Sign in with email using OTP
✅ Sign in with phone number using OTP
❌ Sign in with email using magic link
❌ Sign in with phone number magic link
Getting Started #
Documentation
Developer Account
As mentioned, there are 3 different ways to authenticate users. You can also combine the authentication methods, for example: Register the user after verifying their emails, then use Sign in with device for subsequent logins.
To use this SDK, you can create a free account at Cotter to get your API keys.
For Android #
Update your minSdkVersion to 18 inside android/app/build.gradle
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.example"
minSdkVersion 18 // Update this line
...
}
copied to clipboard
Sign in with device #
Signing in with device works like Google Prompt. It allows users to sign in to your website or app automatically from a device that they trust, or in one-tap by approving the login request from your app.
Quickstart #
Find a quickstart tutorial in our documentation.
Signing Up #
To register a new user, we need to create a new user in Cotter and register the current device as trusted.
Cotter cotter = new Cotter(apiKeyID: API_KEY_ID);
try {
var user = await cotter.signUpWithDevice(identifier: emailAddress);
// You can also verify the user's email here, check
// "Sign in with Email > Verify Email for a logged-in user" below
user = await user.verifyEmailWithOTP(redirectURL: "myexample://auth_callback");
} catch(e) {
print(e);
}
copied to clipboard
Signing In #
To authenticate your user, the SDK will check and verify if the current device is trusted. If it is trusted, users can sign in automatically.
Cotter cotter = new Cotter(apiKeyID: API_KEY_ID);
try {
var event = await cotter.signInWithDevice(
identifier: emailAddress,
context: context,
);
} catch(e) {
print(e);
}
if (event.approved) {
_goToDashboard();
}
copied to clipboard
Signing in from a Trusted Device
If the user signed-in from a trusted device, the event will automatically be approved and the user can proceed to the dashboard.
Signing in from a Non-Trusted Device
Otherwise, the SDK will show a prompt that asks the user to approve the login from the device that they trust. Inside your app in the trusted device, the SDK will show a prompt asking if the user want to approve the login.
// Show prompt to approve the login from the trusted device
Cotter cotter = new Cotter(apiKeyID: API_KEY_ID);
try {
var user = await cotter.getUser();
var event = await user.checkNewSignInRequest(context: context);
} catch(e) {
print(e);
}
copied to clipboard
Sign in with Email / Phone Number #
You can authenticate users by sending a verification code to their email/phone and checking if they can enter the code correctly. Ideally, you would combine this method with the sign up with device method above. For example, there are several flows that you can use:
Sign up and authenticate solely by sending a verification code to the user's email.
Verify the user's email, then register user's device as trusted. Subsequent logins using sign in with device.
Sign up with user's device, then verify user's email after registration. Subsequent logins using sign in with device.
Setup #
The email and phone number verification uses OAuth PKCE flow, which requires the app to open a secure in-app browser to authenticate and redirect back to the app with an authorization code.
To do this, you need to set up deep-linking.
Deep-linking in iOS #
Example URL: myexample://auth_callback. Add the following to your ios/Runner/Info.plist.
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>myexample</string> <!-- 👈 Change this to your own URL Scheme -->
<key>CFBundleURLSchemes</key>
<array>
<string>myexample</string> <!-- 👈 Change this to your own URL Scheme -->
</array>
</dict>
</array>
copied to clipboard
Deep-linking in Android #
Example URL: myexample://auth_callback. Add the following to your android/app/src/main/AndroidManifest.xml.
<manifest ...>
<application ...>
<!-- Add the lines from here -->
<activity android:name="com.linusu.flutter_web_auth.CallbackActivity" >
<intent-filter android:label="flutter_web_auth">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- This is for myexample://auth_callback -->
<!-- 👇 Change this to your own URL scheme -->
<data android:scheme="myexample" android:host="auth_callback"/>
</intent-filter>
</activity>
<!-- Until here -->
</application>
</manifest>
copied to clipboard
Testing deep-linking #
Enter myexample://auth_callback in the simulator's browser and see if it redirects to your app.
Sign in with Email #
Make sure you have set up the deep-linking above.
Signing Up #
This method will:
Verify the user's email
Then create a new user in Cotter if successful
Cotter cotter = new Cotter(apiKeyID: API_KEY_ID);
try {
var user = await cotter.signUpWithEmailOTP(
redirectURL: "myexample://auth_callback",
email: inputController.text, // Optional, if you leave this blank, user can enter email in the in-app browser
);
// If you want to follow flow 2 above, you can register the user's device as trusted here
user = await user.registerDevice();
} catch(e) {
print(e);
}
copied to clipboard
Signing in #
To authenticate by verifying user's email:
This method will create a new user if one doesn't exist.
Cotter cotter = new Cotter(apiKeyID: API_KEY_ID);
try {
var user = await cotter.signInWithEmailOTP(
redirectURL: "myexample://auth_callback",
email: inputController.text, // Optional, if you leave this blank, user can enter email in the in-app browser
);
} catch(e) {
print(e);
}
copied to clipboard
Verify Email for a logged-in user #
To verify the email of a user that is currently logged-in:
Cotter cotter = new Cotter(apiKeyID: API_KEY_ID);
try {
var user = await cotter.getUser();
user = await user.verifyEmailWithOTP(redirectURL: "myexample://auth_callback");
} catch (e) {
print(e);
}
copied to clipboard
Sign in with Phone #
Make sure you have set up the deep-linking above.
Signing Up #
This method will:
Verify the user's phone number
Then create a new user in Cotter if successful
Option 1: You want to use Cotter's input form inside the in-app browser. This helps with validating the input.
Cotter cotter = new Cotter(apiKeyID: API_KEY_ID);
try {
var user = await cotter.signUpWithPhoneOTP(
redirectURL: "myexample://auth_callback",
channels: [PhoneChannel.SMS, PhoneChannel.WHATSAPP], // optional, default is SMS
);
} catch (e) {
print(e);
}
copied to clipboard
Option 2: You want to use your own input form and buttons. You can present 2 buttons to allow sending the OTP via WhatsApp or SMS.
Using SMS:
try {
var user = await cotter.signUpWithPhoneOTPViaSMS(
redirectURL: "myexample://auth_callback",
phone: inputController.text,
);
} catch (e) {
print(e);
}
copied to clipboard
Using WhatsApp:
try {
var user = await cotter.signUpWithPhoneOTPViaWhatsApp(
redirectURL: "myexample://auth_callback",
phone: inputController.text,
);
} catch (e) {
print(e);
}
copied to clipboard
Signing In #
To authenticate by verifying user's phone number:
Option 1: You want to use Cotter's input form inside the in-app browser. This helps with validating the input.
This method will create a new user if one doesn't exist.
Cotter cotter = new Cotter(apiKeyID: API_KEY_ID);
try {
var user = await cotter.signInWithPhoneOTP(
redirectURL: "myexample://auth_callback",
channels: [PhoneChannel.SMS, PhoneChannel.WHATSAPP], // optional, default is SMS
);
} catch (e) {
print(e);
}
copied to clipboard
Option 2: You want to use your own input form and buttons. You can present 2 buttons to allow sending the OTP via WhatsApp or SMS.
Using SMS:
try {
var user = await cotter.signInWithPhoneOTPViaSMS(
redirectURL: "myexample://auth_callback",
phone: inputController.text,
);
} catch (e) {
print(e);
}
copied to clipboard
Using WhatsApp:
try {
var user = await cotter.signInWithPhoneOTPViaWhatsApp(
redirectURL: "myexample://auth_callback",
phone: inputController.text,
);
} catch (e) {
print(e);
}
copied to clipboard
Verify Phone for a logged-in user #
To verify the phone number of a user that is currently logged-in:
Using SMS:
Cotter cotter = new Cotter(apiKeyID: API_KEY_ID);
try {
var user = await cotter.getUser();
user = await user.verifyPhoneWithOTPViaSMS(redirectURL: "myexample://auth_callback");
} catch (e) {
print(e);
}
copied to clipboard
Using WhatsApp:
Cotter cotter = new Cotter(apiKeyID: API_KEY_ID);
try {
var user = await cotter.getUser();
user = await user.verifyPhoneWithOTPViaWhatsApp(redirectURL: "myexample://auth_callback");
} catch (e) {
print(e);
}
copied to clipboard
Getting the logged-in user #
The SDK automatically stores OAuth tokens (access token, id token, and refresh token) in the device's secure storage, along with the user information.
To get the logged-in user information:
Cotter cotter = new Cotter(apiKeyID: API_KEY_ID);
try {
var user = await cotter.getUser();
} catch(e) {
print(e);
}
copied to clipboard
Getting OAuth Tokens #
The SDK can fetch stored tokens for you and refresh them as needed if they're expired.
Cotter cotter = new Cotter(apiKeyID: API_KEY_ID);
try {
var accessToken = await cotter.getAccessToken();
var idToken = await cotter.getIDToken();
var refreshToken = await cotter.getRefreshToken();
} catch (e) {
print(e);
}
copied to clipboard
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.