createLiveUser function
Signs in as a live Okta user with the given username and password, and
returns an AuthUser with the actual tokens from Okta.
The client ID, token URL, and scopes are taken from the current .env file.
The application associated with the client ID must have the resource password grant enabled.
Implementation
Future<AuthUser<OAuthToken>> createLiveUser({
required String username,
required String password,
}) async {
final envFamily = createEnvFamily();
final container = ProviderContainer();
final clientId = await container.read(envFamily('CLIENT_ID').future);
final clientSecret = await container.read(envFamily('CLIENT_SECRET').future);
final clientKey =
clientSecret.isNotEmpty ? '$clientId:$clientSecret' : clientId;
final tokenUrl = await container.read(envFamily('TOKEN_URL').future);
final scopes = await container
.read(envFamily('SCOPES').future)
.then((value) => value.split('|').join(' '));
final response = await post(
Uri.parse(tokenUrl),
headers: {
'Authorization': 'Basic ${base64Encode(utf8.encode(clientKey))}',
},
body: {
'grant_type': 'password',
'username': username,
'password': password,
'scope': scopes,
},
);
final json = jsonDecode(response.body) as Map<String, dynamic>;
final idToken = json['id_token'];
final accessToken = json['access_token'];
if (idToken is! String || accessToken is! String) {
throw ArgumentError('The user could not be logged in. '
'Response from authentication server: ${response.body}');
}
final idTokenJson = parseJwt(idToken);
final accessTokenJson = parseJwt(accessToken);
final expirySeconds = accessTokenJson['exp'] as int;
return createFakeUser(
id: idTokenJson['sub'],
email: idTokenJson['email'],
idToken: idToken,
idTokenJson: idTokenJson,
accessToken: accessToken,
refreshToken: json['refresh_token'],
accesTokenExpiration: DateTime.fromMillisecondsSinceEpoch(
expirySeconds * 1000,
isUtc: true,
),
);
}