Skip to content

Commit c8f321d

Browse files
committed
Visa - Easy third party auth for flutter apps.
0 parents  commit c8f321d

File tree

87 files changed

+2677
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+2677
-0
lines changed

.gitignore

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Miscellaneous
2+
*.class
3+
*.log
4+
*.pyc
5+
*.swp
6+
.DS_Store
7+
.atom/
8+
.buildlog/
9+
.history
10+
.svn/
11+
12+
# IntelliJ related
13+
*.iml
14+
*.ipr
15+
*.iws
16+
.idea/
17+
18+
# The .vscode folder contains launch configuration and tasks you configure in
19+
# VS Code which you may wish to be included in version control, so this line
20+
# is commented out by default.
21+
#.vscode/
22+
23+
# Flutter/Dart/Pub related
24+
**/doc/api/
25+
.dart_tool/
26+
.flutter-plugins
27+
.flutter-plugins-dependencies
28+
.packages
29+
.pub-cache/
30+
.pub/
31+
build/
32+
33+
# Android related
34+
**/android/**/gradle-wrapper.jar
35+
**/android/.gradle
36+
**/android/captures/
37+
**/android/gradlew
38+
**/android/gradlew.bat
39+
**/android/local.properties
40+
**/android/**/GeneratedPluginRegistrant.java
41+
42+
# iOS/XCode related
43+
**/ios/**/*.mode1v3
44+
**/ios/**/*.mode2v3
45+
**/ios/**/*.moved-aside
46+
**/ios/**/*.pbxuser
47+
**/ios/**/*.perspectivev3
48+
**/ios/**/*sync/
49+
**/ios/**/.sconsign.dblite
50+
**/ios/**/.tags*
51+
**/ios/**/.vagrant/
52+
**/ios/**/DerivedData/
53+
**/ios/**/Icon?
54+
**/ios/**/Pods/
55+
**/ios/**/.symlinks/
56+
**/ios/**/profile
57+
**/ios/**/xcuserdata
58+
**/ios/.generated/
59+
**/ios/Flutter/App.framework
60+
**/ios/Flutter/Flutter.framework
61+
**/ios/Flutter/Flutter.podspec
62+
**/ios/Flutter/Generated.xcconfig
63+
**/ios/Flutter/app.flx
64+
**/ios/Flutter/app.zip
65+
**/ios/Flutter/flutter_assets/
66+
**/ios/Flutter/flutter_export_environment.sh
67+
**/ios/ServiceDefinitions.json
68+
**/ios/Runner/GeneratedPluginRegistrant.*
69+
70+
# Exceptions to above rules.
71+
!**/ios/**/default.mode1v3
72+
!**/ios/**/default.mode2v3
73+
!**/ios/**/default.pbxuser
74+
!**/ios/**/default.perspectivev3

.metadata

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# This file tracks properties of this Flutter project.
2+
# Used by Flutter tool to assess capabilities and perform upgrades etc.
3+
#
4+
# This file should be version controlled and should not be manually edited.
5+
6+
version:
7+
revision: 1aafb3a8b9b0c36241c5f5b34ee914770f015818
8+
channel: stable
9+
10+
project_type: package

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## [0.0.1] - TODO: Add release date.
2+
3+
* TODO: Describe initial release.

LICENSE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
TODO: Add your license here.

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# visa
2+
3+
Easy third party authentication.
4+
5+
## Getting Started
6+
7+
This project is a starting point for a Dart
8+
[package](https://flutter.dev/developing-packages/),
9+
a library module containing code that can be shared easily across
10+
multiple Flutter or Dart projects.
11+
12+
For help getting started with Flutter, view our
13+
[online documentation](https://flutter.dev/docs), which offers tutorials,
14+
samples, guidance on mobile development, and a full API reference.

lib/auth-data.dart

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import 'engine/oauth.dart';
2+
3+
class AuthData{
4+
const AuthData({
5+
this.clientID, this.accessToken, this.firstName, this.lastName,
6+
this.userID, this.email, this.profileImgUrl, this.userJson,
7+
this.response,
8+
});
9+
10+
final String userID;
11+
final String clientID;
12+
final String accessToken;
13+
final String firstName;
14+
final String lastName;
15+
final String email;
16+
final String profileImgUrl;
17+
final Map<String, dynamic> userJson;
18+
final Map<String, String> response;
19+
20+
String formatResponse(Map<String, String> response){
21+
StringBuffer result = StringBuffer('\n');
22+
23+
for (MapEntry data in response.entries){
24+
result.write('\t\t\t\t');
25+
result.write(data.key);
26+
result.write(' = ');
27+
result.write(data.value);
28+
result.write('\n');
29+
}
30+
31+
return result.toString();
32+
}
33+
34+
@override
35+
String toString() {
36+
String responseString = formatResponse(response);
37+
return 'AuthData {\n\n'
38+
'\t\ttoken: $accessToken\n\n'
39+
'\t\tuser id: $userID\n\n'
40+
'\t\tfirst name: $firstName\n\n'
41+
'\t\tlast name: $lastName\n\n'
42+
'\t\temail: $email\n\n'
43+
'\t\tprofile image: $profileImgUrl\n\n'
44+
'\t\tresponse: $responseString\n'
45+
'\t\tuser json: $userJson\n\n'
46+
'}';
47+
}
48+
49+
factory AuthData.fromTwitchJson(
50+
Map<String, dynamic> json,
51+
Map<String, String>data
52+
){
53+
final String accessToken = data[OAuth.TOKEN_KEY];
54+
Map<String, dynamic> user = json['data'][0];
55+
56+
return AuthData(
57+
clientID: data['clientID'],
58+
accessToken: accessToken,
59+
userID: user['id'],
60+
email: user['email'] as String,
61+
profileImgUrl: user['profile_image_url'] as String,
62+
response: data,
63+
userJson: json
64+
);
65+
}
66+
67+
factory AuthData.fromDiscordJson(
68+
Map<String, dynamic> json,
69+
Map<String, String>data
70+
){
71+
final String accessToken = data[OAuth.TOKEN_KEY];
72+
final String userId = json['id'] as String;
73+
final String avatar = json['avatar'] as String;
74+
final String profileImgUrl = 'https://cdn.discordapp.com/'
75+
'avatars/$userId/$avatar.png';
76+
77+
return AuthData(
78+
clientID: data['clientID'],
79+
accessToken: accessToken,
80+
userID: userId,
81+
email: json['email'] as String,
82+
profileImgUrl: profileImgUrl,
83+
response: data,
84+
userJson: json
85+
);
86+
}
87+
88+
factory AuthData.fromFbJson(
89+
Map<String, dynamic> json,
90+
Map<String, String>data
91+
){
92+
final String accessToken = data[OAuth.TOKEN_KEY];
93+
final String profileImgUrl = 'https://graph.facebook.com/me/picture'
94+
'?type=large'
95+
'&access_token=$accessToken';
96+
97+
return AuthData(
98+
clientID: data['clientID'],
99+
accessToken: accessToken,
100+
userID: json['id'] as String,
101+
firstName: json['first_name'] as String,
102+
lastName: json['last_name'] as String,
103+
email: json['email'] as String,
104+
profileImgUrl: profileImgUrl,
105+
response: data,
106+
userJson: json
107+
);
108+
}
109+
}

lib/discord.dart

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import 'dart:convert';
2+
import 'package:http/http.dart' as http;
3+
4+
import 'engine/simple-auth.dart';
5+
import 'engine/visa.dart';
6+
import 'auth-data.dart';
7+
import 'engine/oauth.dart';
8+
9+
class DiscordAuth implements Visa{
10+
final baseUrl = 'https://discord.com/api/oauth2/authorize';
11+
SimpleAuth visa;
12+
13+
DiscordAuth(){
14+
visa = SimpleAuth(
15+
baseUrl: baseUrl,
16+
getAuthData: (Map <String, String> data) async {
17+
var token = data[OAuth.TOKEN_KEY];
18+
var baseProfileUrl = 'https://discord.com/api/users/@me';
19+
20+
var profileResponse = await http.get(baseProfileUrl, headers: {
21+
'Authorization': 'Bearer $token',
22+
});
23+
24+
print(profileResponse);
25+
26+
var profileJson = Map<String, dynamic>.from(
27+
json.decode(profileResponse.body)
28+
);
29+
30+
return AuthData.fromDiscordJson(profileJson, data);
31+
}
32+
);
33+
}
34+
}

lib/engine/oauth.dart

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import 'dart:collection';
2+
import 'dart:io';
3+
import 'package:flutter/material.dart';
4+
import 'package:webview_flutter/webview_flutter.dart';
5+
6+
class OAuth{
7+
const OAuth({
8+
@required this.baseUrl,
9+
@required this.clientID,
10+
@required this.redirectUri,
11+
@required this.state,
12+
@required this.scope
13+
});
14+
15+
final String baseUrl;
16+
final String clientID;
17+
final String redirectUri;
18+
final String state;
19+
final String scope;
20+
static const String TOKEN_KEY = 'access_token';
21+
22+
WebView authenticate({@required Function onDone}){
23+
String authUrl = '$baseUrl'
24+
'?client_id=$clientID'
25+
'&redirect_uri=$redirectUri'
26+
'&state=$state'
27+
'&scope=$scope'
28+
'&response_type=token';
29+
30+
if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
31+
32+
return WebView(
33+
initialUrl: authUrl,
34+
javascriptMode: JavascriptMode.unrestricted,
35+
onPageStarted: (url) async {
36+
if (url.startsWith(redirectUri)){
37+
var returnedData = _getQueryParams(url);
38+
returnedData['clientID'] = clientID;
39+
onDone(returnedData);
40+
}
41+
}
42+
);
43+
}
44+
45+
Map<String, String> _getQueryParams(String url){
46+
final List<String> urlParams = url.split(RegExp('[?&# ]'));
47+
final Map<String, String> queryParams = HashMap();
48+
List<String> parts;
49+
50+
for(String param in urlParams){
51+
if (!param.contains('=')) continue;
52+
53+
parts = param.split('=');
54+
queryParams[parts[0]] = parts[1];
55+
}
56+
57+
return queryParams;
58+
}
59+
}
60+

lib/engine/simple-auth.dart

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import 'package:meta/meta.dart';
2+
import 'package:webview_flutter/webview_flutter.dart';
3+
4+
import '../auth-data.dart';
5+
import 'oauth.dart';
6+
7+
class SimpleAuth{
8+
const SimpleAuth ({
9+
@required this.baseUrl, @required this.getAuthData
10+
});
11+
12+
final String baseUrl;
13+
final Function getAuthData;
14+
15+
WebView authenticate({
16+
@required String clientID, @required String redirectUri,
17+
@required String state, @required String scope, @required Function onDone
18+
}){
19+
final OAuth oAuth = OAuth(
20+
baseUrl: baseUrl,
21+
clientID: clientID,
22+
redirectUri: redirectUri,
23+
state: state,
24+
scope: scope,
25+
);
26+
27+
return oAuth.authenticate(onDone: (token) async {
28+
AuthData authData = await getAuthData(token);
29+
onDone(authData);
30+
});
31+
}
32+
}

lib/engine/visa.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import 'simple-auth.dart';
2+
3+
abstract class Visa{
4+
SimpleAuth visa;
5+
}

0 commit comments

Comments
 (0)