44

I want to encode the following string in Base64Url in Flutter and decode it in on a Dart server.

"username:password"

How do I do that? And how do I do it in Base64?

Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
  • 5
    Possible duplicate of [How to pass basic auth credentials in API call for a Flutter mobile application?](https://stackoverflow.com/questions/50244416/how-to-pass-basic-auth-credentials-in-api-call-for-a-flutter-mobile-application) – Richard Heap May 18 '19 at 19:47
  • 1
    Also related [How to native convert string -> base64 and base64 -> string](https://stackoverflow.com/questions/14755421/how-to-native-convert-string-base64-and-base64-string) – Herohtar May 18 '19 at 20:51
  • 2
    I would like to include Base64Url since sometimes it is a requirement. The linked questions, while useful, don't ask or answer that. – Suragch May 18 '19 at 22:59

1 Answers1

124

The dart:convert library contains an encoder and decoder for Base64 and Base64Url. However, they encode and decode Lists of integers, so for strings you also need to encode and decode in UTF-8. Rather than doing these two encodings separately, you can combine them with fuse.

You need to have the following import:

import 'dart:convert';

Base64

String credentials = "username:password";
Codec<String, String> stringToBase64 = utf8.fuse(base64);
String encoded = stringToBase64.encode(credentials);      // dXNlcm5hbWU6cGFzc3dvcmQ=
String decoded = stringToBase64.decode(encoded);          // username:password

Note that this is equivalent to:

String encoded = base64.encode(utf8.encode(credentials)); // dXNlcm5hbWU6cGFzc3dvcmQ=
String decoded = utf8.decode(base64.decode(encoded));     // username:password

Base64Url

String credentials = "username:password";
Codec<String, String> stringToBase64Url = utf8.fuse(base64Url);
String encoded = stringToBase64Url.encode(credentials);      // dXNlcm5hbWU6cGFzc3dvcmQ=
String decoded = stringToBase64Url.decode(encoded);          // username:password

Again, this is equivalent to:

String encoded = base64Url.encode(utf8.encode(credentials)); // dXNlcm5hbWU6cGFzc3dvcmQ=
String decoded = utf8.decode(base64Url.decode(encoded));     // username:password

See also

Community
  • 1
  • 1
Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
  • 1
    instead of constructs like `utf8.decode(base64.decode(credentials));` use `Codec::fuse()` method – pskink May 18 '19 at 17:14
  • @pskink, At first I couldn't wrap my mind around what was happening (the expanded form felt more readable), but then I realized that you didn't need to switch the order of `utf8` and `base64`. You just use `decode` on the fused method. So, yes, much easier. – Suragch May 18 '19 at 18:14
  • 3
    this is because `fuse()` method docs say: *"When encoding, the resulting codec encodes with `this` before encoding with `other`. When decoding, the resulting codec decodes with `other` before decoding with `this`."* – pskink May 18 '19 at 18:32
  • 1
    btw fuse is not limited to two codecs - you can call multiple fuse methods to chain more than two codecs – pskink May 18 '19 at 20:50
  • @pskink I also found this one: `Base64Encoder().convert(credentials.codeUnits)`, where you can also do `Base64Encoder.urlSafe()`. What are your thoughts on this? It seems more readable to me. – Suragch May 18 '19 at 22:55
  • this is [Base64Codec.encoder](https://api.flutter.dev/flutter/dart-convert/Base64Codec/encoder.html) - the same like `base64.encoder` – pskink May 19 '19 at 05:29