Skip to content

Commit

Permalink
Sbr/feat microsoft oauth mobile (#124)
Browse files Browse the repository at this point in the history
* feat(oauth): getting microsoft access token via oauth

* feat(style): changed button with microsoft icons

* fix(spotify): removed useless spotify oauth code

* fix(warnings): removed unnecessary comments and warnings

---------

Signed-off-by: Samuel Bruschet <[email protected]>
  • Loading branch information
sambrus authored Dec 5, 2024
1 parent c2d2010 commit 805608d
Show file tree
Hide file tree
Showing 13 changed files with 303 additions and 318 deletions.
4 changes: 2 additions & 2 deletions client_mobile/android/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ pluginManagement {

plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "7.3.0" apply false
id "org.jetbrains.kotlin.android" version "1.7.10" apply false
id "com.android.application" version "7.3.1" apply false
id "org.jetbrains.kotlin.android" version "2.1.0" apply false
}

include ":app"
Binary file added client_mobile/assets/images/microsoft_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
230 changes: 49 additions & 181 deletions client_mobile/lib/features/auth/login.dart
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
// import 'dart:io';
import 'package:client_mobile/services/microsoft/microsoft_auth_service.dart';
import 'package:client_mobile/widgets/button.dart';
import 'package:client_mobile/widgets/clickable_text.dart';
import 'package:client_mobile/widgets/form_field.dart';
import 'package:client_mobile/widgets/sign_in_button.dart';
import 'package:client_mobile/widgets/simple_text.dart';
import 'package:flutter/material.dart';
import 'package:flutter_appauth/flutter_appauth.dart';
import 'package:flutter_web_auth/flutter_web_auth.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart';
import 'package:oauth2/oauth2.dart' as oauth2;
// import 'package:http/http.dart' as http;
import 'package:flutter_dotenv/flutter_dotenv.dart';
// import 'package:oauth2_client/access_token_response.dart';
// import 'package:oauth2_client/authorization_response.dart';
// import 'package:oauth2_client/spotify_oauth2_client.dart';

class LoginPage extends StatefulWidget {
@override
Expand All @@ -23,190 +17,64 @@ class LoginPage extends StatefulWidget {

class _LoginPageState extends State<LoginPage> {
final String callbackUrlScheme = 'my.area.app';
String get redirectUrlMobile => '$callbackUrlScheme://callback';
String get spotifyRedirectUrlMobile => '$callbackUrlScheme://callback';

final String clientId = dotenv.env["VITE_SPOTIFY_CLIENT_ID"] ?? "";
final appAuth = FlutterAppAuth();
final String clientSecret = dotenv.env["VITE_SPOTIFY_CLIENT_SECRET"] ?? "";
final String issuer = "https://accounts.spotify.com/";
final Uri authorizationEndpoint =
Uri.parse('https://accounts.spotify.com/authorize');
final Uri tokenEndpoint = Uri.parse('https://accounts.spotify.com/api/token');
final String redirectUrlWeb = "https://localhost:8081/auth/spotify/callback";
final Uri redirectUri =
Uri.parse('https://localhost:8081/auth/spotify/callback');
oauth2.Client? client;

Future<void> authenticateWithSpotify() async {
try {
final String spotifyUrl = 'https://accounts.spotify.com/authorize'
'&client_id=$clientId'
'&redirect_uri=$redirectUrlMobile';

print("Authentification en cours ...");
final result = await FlutterWebAuth.authenticate(
url: spotifyUrl,
callbackUrlScheme: callbackUrlScheme,
);

print("voici le résultat : ${result}");
} catch (e) {
print("erreur d'authentification : ${e}");
}
}

Future<void> authenticateWithSpotifyOld() async {
try {
// print("client id : ${clientId}");
// AccessTokenResponse? accessToken;
// SpotifyOAuth2Client client = SpotifyOAuth2Client(
// redirectUri: redirectUrlMobile,
// customUriScheme: "my.area.app"
// );

// var authResp =
// await client.requestAuthorization(clientId: clientId, customParams: {
// // 'show_dialog': 'true'
// }, scopes: [
// 'user-read-private',
// 'user-read-playback-state',
// 'user-modify-playback-state',
// 'user-read-currently-playing',
// 'user-read-email'
// ]);
// var authCode = authResp.code;

// print("auth code : ${authCode}");

final authorizationTokenRequest = AuthorizationTokenRequest(
clientId, redirectUrlMobile,
issuer: issuer,
clientSecret: clientSecret,
scopes: ["openid", "profile", "email", "offline_access"],
additionalParameters: {'show_dialog': 'true'});

final result =
await appAuth.authorizeAndExchangeCode(authorizationTokenRequest);

print("--------------------------------");
print("");
print("");
print("Le code échangé est le suivant : ${result}");
print("");
print("");
print("--------------------------------");

return;
// Start a small HTTP server to capture the callback
// final server = await HttpServer.bind(InternetAddress.loopbackIPv4, 8080);
// print("Listening on ${server.address}:${server.port}");

// // Build the OAuth2 flow
// final grant = oauth2.AuthorizationCodeGrant(
// clientId,
// authorizationEndpoint,
// tokenEndpoint,
// secret: clientSecret,
// httpClient: http.Client(),
// );

// // Generate the authorization URL
// final authorizationUrl = grant.getAuthorizationUrl(redirectUri, scopes: [
// 'user-read-email',
// 'user-read-private',
// ]);

// // Open the browser for user login
// print('Opening browser: $authorizationUrl');
// await Process.run('open', [authorizationUrl.toString()]);

// // Wait for the callback
// final request = await server.first;

// // Validate and close the server
// final queryParameters = request.uri.queryParameters;
// final code = queryParameters['code'];
// final state = queryParameters['state'];
// request.response
// ..statusCode = 200
// ..headers.set('Content-Type', ContentType.html.mimeType)
// ..write('You can now close this page.')
// ..close();
// await server.close();

// // Exchange the authorization code for tokens
// if (code != null) {
// client = await grant.handleAuthorizationCode(code);
// setState(() {});
// print(
// 'Authenticated successfully! Access token: ${client?.credentials.accessToken}');
// }
} catch (e) {
print('Authentication failed: $e');
}
}
final appAuth = const FlutterAppAuth();

@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: client == null
? Container(
padding: const EdgeInsets.all(20),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SimpleText(
"Email",
bold: true,
),
const AreaFormField(label: "Value"),
const SizedBox(height: 50),
const SimpleText("Password", bold: true),
const AreaFormField(label: "Value"),
const SizedBox(height: 15),
Align(
alignment: Alignment.center,
child: AreaButton(
label: "Login",
onPressed: () {},
color: Colors.black,
),
),
const SizedBox(height: 30),
Align(
alignment: Alignment.center,
child: SignInButton(
onPressed: () {
authenticateWithSpotifyOld();
},
label: "Sign in with Spotify",
icon: const FaIcon(
size: 34,
FontAwesomeIcons.spotify,
color: Colors.green,
),
),
),
const SizedBox(height: 5),
Align(
alignment: Alignment.center,
child: SmallClickableText(
"I don't have an account",
onPressed: () {
context.push("/register");
},
),
)
],
child: Container(
padding: const EdgeInsets.all(20),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SimpleText(
"Email",
bold: true,
),
const AreaFormField(label: "Value"),
const SizedBox(height: 50),
const SimpleText("Password", bold: true),
const AreaFormField(label: "Value"),
const SizedBox(height: 15),
AreaButton(
label: "Login",
onPressed: () {},
color: Colors.black,
),
const SizedBox(height: 30),
Align(
alignment: Alignment.center,
child: SignInButton(
onPressed: () {
MicrosoftAuthService.auth(context);
},
label: "Sign in with Microsoft",
image: Image.asset(
"assets/images/microsoft_logo.png",
width: 40,
height: 30,
),
),
),
const SizedBox(height: 5),
Align(
alignment: Alignment.center,
child: SmallClickableText(
"I don't have an account",
onPressed: () {
context.push("/register");
},
),
)
: Text(
'Authenticated! Access token: ${client?.credentials.accessToken}'),
),
],
),
),
)),
);
}
}
Loading

0 comments on commit 805608d

Please sign in to comment.