add authentication service

This commit is contained in:
cuqmbr 2023-11-12 10:01:21 +02:00
parent 2cd69a5ddd
commit dd742882fd
Signed by: cuqmbr
GPG Key ID: 2D72ED98B6CB200F
5 changed files with 586 additions and 0 deletions

View File

@ -0,0 +1,10 @@
class JwtClaims {
static const String id = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier';
static const String email = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress';
static const String phone = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mobilephone';
static const String roles ='http://schemas.microsoft.com/ws/2008/06/identity/claims/role';
}

View File

@ -0,0 +1,10 @@
class GlobalUser {
static String? id;
static String? email;
static String? phone;
static List<String>? roles;
}

View File

@ -0,0 +1,170 @@
import 'package:graphql/client.dart';
import 'package:jwt_decoder/jwt_decoder.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:shopping_assistant_mobile_client/constants/jwt_claims.dart';
import 'package:uuid/uuid.dart';
class AuthenticationService {
final GraphQLClient client = GraphQLClient(
cache: GraphQLCache(),
link: HttpLink('https://shopping-assistant-api-dev.azurewebsites.net/graphql'),
);
late SharedPreferences prefs;
AuthenticationService() {
SharedPreferences.getInstance().then((result) => {prefs = result});
}
Future<String> getAccessToken() async {
var accessToken = prefs.getString('accessToken');
var refreshToken = prefs.getString('refreshToken');
if (accessToken == null && refreshToken != null) {
print('WTF??');
} else if (accessToken == null && refreshToken == null) {
accessToken = await accessGuest();
print('Got new access token $accessToken');
} else if (JwtDecoder.isExpired(accessToken!)) {
accessToken = await refreshAccessToken();
print('Refreshed access token $accessToken');
}
print('Returned access token $accessToken');
return accessToken!;
}
Future login(String? email, String? phone, String password) async {
const String loginQuery = r'''
mutation Login($login: AccessUserModelInput!) {
login(login: $login) {
accessToken
refreshToken
}
}
''';
final MutationOptions options = MutationOptions(
document: gql(loginQuery),
variables: <String, dynamic>{
'login': {
'email': email,
'phone': phone,
'password': password,
},
},
);
final QueryResult result = await client.mutate(options);
if (result.hasException) {
print(result.exception.toString());
}
final accessToken = result.data?['login']['accessToken'] as String;
final refreshToken = result.data?['login']['refreshToken'] as String;
prefs.setString('accessToken', accessToken);
prefs.setString('refreshToken', refreshToken);
}
Future<String> accessGuest() async {
String? guestId = prefs.getString('guestId');
guestId ??= const Uuid().v4();
prefs.setString('guestId', guestId);
const String accessGuestMutation = r'''
mutation AccessGuest($guest: AccessGuestModelInput!) {
accessGuest(guest: $guest) {
accessToken
refreshToken
}
}
''';
final MutationOptions options = MutationOptions(
document: gql(accessGuestMutation),
variables: <String, dynamic>{
'guest': {'guestId': guestId},
},
);
final QueryResult result = await client.mutate(options);
if (result.hasException) {
print(result.exception.toString());
}
final String accessToken =
result.data?['accessGuest']['accessToken'] as String;
final String refreshToken =
result.data?['accessGuest']['refreshToken'] as String;
prefs.setString('accessToken', accessToken);
prefs.setString('refreshToken', refreshToken);
return accessToken;
}
Future<String> refreshAccessToken() async {
var accessToken = prefs.getString('accessToken');
var refreshToken = prefs.getString('refreshToken');
const String refreshAccessTokenMutation = r'''
mutation RefreshAccessToken($model: TokensModelInput!) {
refreshAccessToken(model: $model) {
accessToken
refreshToken
}
}
''';
final QueryOptions options = QueryOptions(
document: gql(refreshAccessTokenMutation),
variables: <String, dynamic>{
'model': {
'accessToken': accessToken,
'refreshToken': refreshToken,
},
},
);
final QueryResult result = await client.query(options);
if (result.hasException) {
print(result.exception.toString());
}
accessToken = result.data?['refreshAccessToken']['accessToken'] as String;
refreshToken = result.data?['refreshAccessToken']['refreshToken'] as String;
prefs.setString('accessToken', accessToken);
prefs.setString('refreshToken', refreshToken);
return accessToken;
}
String getIdFromAccessToken(String accessToken) {
var decodedToken = JwtDecoder.decode(accessToken);
return decodedToken[JwtClaims.id];
}
String getEmailFromAccessToken(String accessToken) {
var decodedToken = JwtDecoder.decode(accessToken);
return decodedToken[JwtClaims.email];
}
String getPhoneFromAccessToken(String accessToken) {
var decodedToken = JwtDecoder.decode(accessToken);
return decodedToken[JwtClaims.phone];
}
// List<String> getRolesFromAccessToken(String accessToken) {
// var decodedToken = JwtDecoder.decode(accessToken);
// List<String> roles = [];
// for (var role in decodedToken[JwtClaims.roles] as List<dynamic>) {
// roles.add(role);
// }
// return roles;
// }
}

View File

@ -1,6 +1,14 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
args:
dependency: transitive
description:
name: args
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
url: "https://pub.dev"
source: hosted
version: "2.4.2"
async:
dependency: transitive
description:
@ -41,6 +49,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.17.2"
connectivity_plus:
dependency: transitive
description:
name: connectivity_plus
sha256: b502a681ba415272ecc41400bd04fe543ed1a62632137dc84d25a91e7746f55f
url: "https://pub.dev"
source: hosted
version: "5.0.1"
connectivity_plus_platform_interface:
dependency: transitive
description:
name: connectivity_plus_platform_interface
sha256: cf1d1c28f4416f8c654d7dc3cd638ec586076255d407cef3ddbdaf178272a71a
url: "https://pub.dev"
source: hosted
version: "1.2.4"
crypto:
dependency: transitive
description:
name: crypto
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
url: "https://pub.dev"
source: hosted
version: "3.0.3"
cupertino_icons:
dependency: "direct main"
description:
@ -49,6 +81,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.6"
dbus:
dependency: transitive
description:
name: dbus
sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263"
url: "https://pub.dev"
source: hosted
version: "0.7.8"
fake_async:
dependency: transitive
description:
@ -57,11 +97,35 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.1"
ffi:
dependency: transitive
description:
name: ffi
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
file:
dependency: transitive
description:
name: file
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
url: "https://pub.dev"
source: hosted
version: "7.0.0"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_hooks:
dependency: transitive
description:
name: flutter_hooks
sha256: "7c8db779c2d1010aa7f9ea3fbefe8f86524fcb87b69e8b0af31e1a4b55422dec"
url: "https://pub.dev"
source: hosted
version: "0.20.3"
flutter_lints:
dependency: "direct dev"
description:
@ -75,6 +139,123 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
gql:
dependency: transitive
description:
name: gql
sha256: e5225e3be4d7eb4027406ab07cb68ad3a089deb3f7f6dc46edbdec78f2e5549f
url: "https://pub.dev"
source: hosted
version: "1.0.1-alpha+1696717343881"
gql_dedupe_link:
dependency: transitive
description:
name: gql_dedupe_link
sha256: "79625bc8029755ce6b26483adf0255c6b6114acc56e7ef81469a99f1ce2296db"
url: "https://pub.dev"
source: hosted
version: "2.0.4-alpha+1696717344020"
gql_error_link:
dependency: transitive
description:
name: gql_error_link
sha256: bfdb543137da89448cc5d003fd029c2e8718931d39d4a7dedb16f9169862fbb9
url: "https://pub.dev"
source: hosted
version: "1.0.0"
gql_exec:
dependency: transitive
description:
name: gql_exec
sha256: da419a3ebaae7672ed662c42d754ffba996347af7fe0ca031f1dd699334994d8
url: "https://pub.dev"
source: hosted
version: "1.0.1-alpha+1696717343896"
gql_http_link:
dependency: transitive
description:
name: gql_http_link
sha256: "0789d397d46ce274942fcc73e18a080cd2584296dadc33d8ae53d0666d7fe981"
url: "https://pub.dev"
source: hosted
version: "1.0.1"
gql_link:
dependency: transitive
description:
name: gql_link
sha256: bcbb09ae8b200f413aa2d21fbf6ce4c4ac1ac443e81c612f29ef1587f4c84122
url: "https://pub.dev"
source: hosted
version: "1.0.1-alpha+1696717343909"
gql_transform_link:
dependency: transitive
description:
name: gql_transform_link
sha256: "0645fdd874ca1be695fd327271fdfb24c0cd6fa40774a64b946062f321a59709"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
graphql:
dependency: "direct main"
description:
name: graphql
sha256: "4ac531068107dffef188c74e7ff662777b729e9d5e0686f71623d4af1e3751c8"
url: "https://pub.dev"
source: hosted
version: "5.2.0-beta.6"
graphql_flutter:
dependency: "direct main"
description:
name: graphql_flutter
sha256: "39b5e830bc654ab02c5b776c31675841d1a8c95840fdd284efba713b1d47e65d"
url: "https://pub.dev"
source: hosted
version: "5.2.0-beta.6"
hive:
dependency: transitive
description:
name: hive
sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941"
url: "https://pub.dev"
source: hosted
version: "2.2.3"
http:
dependency: "direct main"
description:
name: http
sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
http_parser:
dependency: transitive
description:
name: http_parser
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
url: "https://pub.dev"
source: hosted
version: "4.0.2"
js:
dependency: transitive
description:
name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
url: "https://pub.dev"
source: hosted
version: "0.6.7"
jwt_decoder:
dependency: "direct main"
description:
name: jwt_decoder
sha256: "54774aebf83f2923b99e6416b4ea915d47af3bde56884eb622de85feabbc559f"
url: "https://pub.dev"
source: hosted
version: "2.0.1"
lints:
dependency: transitive
description:
@ -107,6 +288,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.9.1"
nm:
dependency: transitive
description:
name: nm
sha256: "2c9aae4127bdc8993206464fcc063611e0e36e72018696cd9631023a31b24254"
url: "https://pub.dev"
source: hosted
version: "0.5.0"
normalize:
dependency: transitive
description:
name: normalize
sha256: "8a60e37de5b608eeaf9b839273370c71ebba445e9f73b08eee7725e0d92dbc43"
url: "https://pub.dev"
source: hosted
version: "0.8.2+1"
path:
dependency: transitive
description:
@ -115,6 +312,142 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.8.3"
path_provider:
dependency: transitive
description:
name: path_provider
sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa
url: "https://pub.dev"
source: hosted
version: "2.1.1"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72
url: "https://pub.dev"
source: hosted
version: "2.2.1"
path_provider_foundation:
dependency: transitive
description:
name: path_provider_foundation
sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d"
url: "https://pub.dev"
source: hosted
version: "2.3.1"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
url: "https://pub.dev"
source: hosted
version: "2.2.1"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170"
url: "https://pub.dev"
source: hosted
version: "2.2.1"
petitparser:
dependency: transitive
description:
name: petitparser
sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750
url: "https://pub.dev"
source: hosted
version: "5.4.0"
platform:
dependency: transitive
description:
name: platform
sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59"
url: "https://pub.dev"
source: hosted
version: "3.1.3"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d
url: "https://pub.dev"
source: hosted
version: "2.1.6"
rxdart:
dependency: transitive
description:
name: rxdart
sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb"
url: "https://pub.dev"
source: hosted
version: "0.27.7"
shared_preferences:
dependency: "direct main"
description:
name: shared_preferences
sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02"
url: "https://pub.dev"
source: hosted
version: "2.2.2"
shared_preferences_android:
dependency: transitive
description:
name: shared_preferences_android
sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06"
url: "https://pub.dev"
source: hosted
version: "2.2.1"
shared_preferences_foundation:
dependency: transitive
description:
name: shared_preferences_foundation
sha256: "7bf53a9f2d007329ee6f3df7268fd498f8373602f943c975598bbb34649b62a7"
url: "https://pub.dev"
source: hosted
version: "2.3.4"
shared_preferences_linux:
dependency: transitive
description:
name: shared_preferences_linux
sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa"
url: "https://pub.dev"
source: hosted
version: "2.3.2"
shared_preferences_platform_interface:
dependency: transitive
description:
name: shared_preferences_platform_interface
sha256: d4ec5fc9ebb2f2e056c617112aa75dcf92fc2e4faaf2ae999caa297473f75d8a
url: "https://pub.dev"
source: hosted
version: "2.3.1"
shared_preferences_web:
dependency: transitive
description:
name: shared_preferences_web
sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf
url: "https://pub.dev"
source: hosted
version: "2.2.1"
shared_preferences_windows:
dependency: transitive
description:
name: shared_preferences_windows
sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59"
url: "https://pub.dev"
source: hosted
version: "2.3.2"
sky_engine:
dependency: transitive
description: flutter
@ -168,6 +501,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.6.0"
typed_data:
dependency: transitive
description:
name: typed_data
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
url: "https://pub.dev"
source: hosted
version: "1.3.2"
uuid:
dependency: "direct main"
description:
name: uuid
sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313"
url: "https://pub.dev"
source: hosted
version: "3.0.7"
vector_math:
dependency: transitive
description:
@ -184,5 +533,46 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.1.4-beta"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b
url: "https://pub.dev"
source: hosted
version: "2.4.0"
win32:
dependency: transitive
description:
name: win32
sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3"
url: "https://pub.dev"
source: hosted
version: "5.0.9"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2"
url: "https://pub.dev"
source: hosted
version: "1.0.3"
xml:
dependency: transitive
description:
name: xml
sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84"
url: "https://pub.dev"
source: hosted
version: "6.3.0"
yaml:
dependency: transitive
description:
name: yaml
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
url: "https://pub.dev"
source: hosted
version: "3.1.2"
sdks:
dart: ">=3.1.4 <4.0.0"
flutter: ">=3.7.0"

View File

@ -35,6 +35,12 @@ dependencies:
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
http: ^1.1.0
jwt_decoder: ^2.0.1
graphql: ^5.2.0-beta.6
shared_preferences: ^2.2.2
uuid: ^3.0.7
graphql_flutter: ^5.2.0-beta.6
dev_dependencies:
flutter_test: