Magic URL authentication with Flutter + Appwrite
Tags: flutter, opensource, news, serverless
Published: 2021-09-08 09:40:27

Appwrite 0.10 introduced **Magic URL** a password-less authentication method. This allows developers to authenticate their users using an email and a URL sent via an E-Mail.

![Frame 30 (2)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nxh1ut0173dso0r3kwh4.png)
 

## ⚙️ Setup
In this tutorial we will learn how we can use Magic URL Authentication in our Flutter applications using Appwrite's [Flutter SDK](https://appwrite.io/docs/getting-started-for-flutter). The same can be done with our [Web SDK](https://appwrite.io/docs/getting-started-for-web) and [Android SDK](https://appwrite.io/docs/getting-started-for-android). As this feature needs to send an email, you must properly setup SMTP service in Appwrite. If you have not already, you can follow [this guide to setup SMTP](https://dev.to/appwrite/30daysofappwrite-getting-started-with-smtp-1e2e) in your Appwrite server.

First, add the Flutter SDK to our Flutter project. From the terminal, in your project's directory enter the following command to add the SDK

```bash
flutter pub add appwrite
```
Next, import and initialize the SDK with your project ID which can be found in your project settings page in Appwrite's console:

```dart
import 'package:appwrite/appwrite.dart';

final client = new Client();

client
    .setEndpoint('http://localhost/v1') // Your Appwrite Endpoint
    .setProject('455x34dfkj') // Your Appwrite Project ID
;
```

Finally, update the **AndroidManifest.xml** file if you are on Android to handle the redirection after handling the login with magic URL as follows:

```xml
<manifest>
  <application>
    <!-- ... -->
    <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" />
        <data android:scheme="appwrite-callback-[PROJECT_ID]" />
      </intent-filter>
    </activity>
    <!-- ... -->
  </application>
</manifest>
```

## 🎩 Create a Magic URL

Once your SDK is setup, access the **Account service** and call the [`createMagicURLSession()`](https://appwrite.io/docs/client/account?sdk=web#accountCreateMagicURLSession) method. This method accepts an e-mail address and a redirect URL as arguments. The redirect URL is optional, but should be provided if you want to handle the completion of magic URL session and redirection yourself.

```js
// Initiate the Magic URL login
final account = Account(client);
try {
    final res = await account.createMagicURLSession(email: 'name@example.com');
    print(res.data);
} on AppwriteException catch(e) {
    print(e.message);
}
```

If the [`createMagicURLSession()`](https://appwrite.io/docs/client/account?sdk=web#accountCreateMagicURLSession) method completes without error, the request sends the user an email with a URL containing a secret key for the next step. If the URL is not provided, the URL of your Appwrite instance is used where there is an inbuilt function to handle the [completion of magic URL session](https://github.com/appwrite/appwrite/blob/master/app/views/home/auth/magicURL.phtml). When the user clicks the link, they are redirected back to the URL provided with the secret `key` and `userId` values attached to the URL query string. This link is valid for 1 hour. If the e-mail passed did not belong to any existing user - this request will also create a user for the passed e-mail address.

If you do not provide a redirect URL, your Appwrite instance will automatically handle the completion and redirection and you should be redirected back to your mobile App. For this, make sure you are able to access the Appwrite instance from your mobile. It's best to host it somewhere with a proper domain. If not use services like [ngrok](https://ngrok.com/) to tunnel your localhost to a temporary domain.

## 🔐 Login with a Magic URL

If you do want to handle the completion of magic URL session and redirection yourself, you need to build a web app that can handle the process. And you need to pass the URL of this web app in the URL parameter while calling `createMagicURLSession`.

For that, use the [`updateMagicURLSession()`](https://appwrite.io/docs/client/account?sdk=web#accountUpdateMagicURLSession) method and call it with the secret and userId values from the URL's query string.

> Please note that in order to avoid a [Redirect Attack](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) the only valid redirect URLs are the ones from domains you have set when adding your platforms in the console interface.


```js
const urlParams = new URLSearchParams(window.location.search);
const userId = urlParams.get('userId');
const secret = urlParams.get('secret');

let promise = appwrite.account.updateMagicURLSession(userId, secret);

promise.then(function (response) {
    console.log(response); // Success
}, function (error) {
    console.log(error); // Failure
});
```

If the [`updateMagicURLSession()`](https://appwrite.io/docs/client/account?sdk=web#accountUpdateMagicURLSession) succeeded, the user is now logged in. 

> Note that once a link is used, it cannot be used again.

## 🏁 Conclusion

We hope you will enjoy this new Appwrite feature and hope this will be useful for lots of applications. If you need help or encounter any difficulties setting up Magic URL Login with Appwrite, please [join our Discord](https://appwrite.io/discord).

### 🔖 References

- [Appwrite Discord](https://appwrite.io/discord)
- [Getting Started with Flutter](https://appwrite.io/docs/getting-started-for-flutter)
- [Appwrite Documentation](https://appwrite.io/docs)