All Projects → e-oj → Visa

e-oj / Visa

Licence: mit
Easy third party authentication (OAuth 2.0) for Flutter apps.

Programming Languages

dart
5743 projects

Projects that are alternatives of or similar to Visa

Vue Authenticate
Simple Vue.js authentication library
Stars: ✭ 1,350 (+2600%)
Mutual labels:  authentication, oauth2, oauth
Oauthlib
A generic, spec-compliant, thorough implementation of the OAuth request-signing logic
Stars: ✭ 2,323 (+4546%)
Mutual labels:  authentication, oauth2, oauth
Fosite
Extensible security first OAuth 2.0 and OpenID Connect SDK for Go.
Stars: ✭ 1,738 (+3376%)
Mutual labels:  authentication, oauth2, oauth
Ueberauth
An Elixir Authentication System for Plug-based Web Applications
Stars: ✭ 1,259 (+2418%)
Mutual labels:  authentication, oauth2, oauth
Retroauth
A library build on top of retrofit, for simple handling of authenticated requests
Stars: ✭ 405 (+710%)
Mutual labels:  authentication, oauth2, oauth
External Auth Server
easy auth for reverse proxies
Stars: ✭ 189 (+278%)
Mutual labels:  authentication, oauth2, oauth
Pizzly
The simplest, fastest way to integrate your app with an OAuth API 😋
Stars: ✭ 796 (+1492%)
Mutual labels:  authentication, oauth2, oauth
Grant
OAuth Proxy
Stars: ✭ 3,509 (+6918%)
Mutual labels:  authentication, oauth2, oauth
Oauth
🔗 OAuth 2.0 implementation for various providers in one place.
Stars: ✭ 336 (+572%)
Mutual labels:  authentication, oauth2, oauth
React Aad
A React wrapper for Azure AD using the Microsoft Authentication Library (MSAL). The easiest way to integrate AzureAD with your React for authentication.
Stars: ✭ 324 (+548%)
Mutual labels:  authentication, oauth2, oauth
Next Auth
Authentication for Next.js
Stars: ✭ 8,362 (+16624%)
Mutual labels:  authentication, oauth2, oauth
Doorkeeper
Doorkeeper is an OAuth 2 provider for Ruby on Rails / Grape.
Stars: ✭ 4,917 (+9734%)
Mutual labels:  authentication, oauth2, oauth
Play Silhouette
Silhouette is an authentication library for Play Framework applications that supports several authentication methods, including OAuth1, OAuth2, OpenID, CAS, 2FA, TOTP, Credentials, Basic Authentication or custom authentication schemes.
Stars: ✭ 826 (+1552%)
Mutual labels:  authentication, oauth2, oauth
Mod auth openidc
OpenID Connect Relying Party implementation for Apache HTTP Server 2.x
Stars: ✭ 677 (+1254%)
Mutual labels:  oauth2, oauth
Aspnet5identityserverangularimplicitflow
OpenID Connect Code / Implicit Flow with Angular and ASP.NET Core 5 IdentityServer4
Stars: ✭ 670 (+1240%)
Mutual labels:  authentication, oauth2
Socialite
Socialite is an OAuth2 Authentication tool. It is inspired by laravel/socialite, you can easily use it without Laravel.
Stars: ✭ 1,026 (+1952%)
Mutual labels:  oauth2, oauth
Fw Cloud Framework
基于springcloud全家桶开发分布式框架(支持oauth2认证授权、SSO登录、统一下单、微信公众号服务、Shardingdbc分库分表、常见服务监控、链路监控、异步日志、redis缓存等功能),实现基于Vue全家桶等前后端分离项目工程
Stars: ✭ 717 (+1334%)
Mutual labels:  oauth2, oauth
Rack Oauth2
OAuth 2.0 Server & Client Library. Both Bearer and MAC token type are supported.
Stars: ✭ 652 (+1204%)
Mutual labels:  oauth2, oauth
Spring Boot React Oauth2 Social Login Demo
Spring Boot React OAuth2 Social Login with Google, Facebook, and Github
Stars: ✭ 676 (+1252%)
Mutual labels:  authentication, oauth2
Auth0.js
Auth0 headless browser sdk
Stars: ✭ 755 (+1410%)
Mutual labels:  authentication, oauth2

visa

Buy Me A Coffee

This is an OAuth 2.0 package that makes it super easy to add third party authentication to flutter apps. It has support for FB, Google, Discord, Twitch, and Github auth. It also provides support for adding new OAuth providers. You can read this medium article for a brief introduction.

Demo

demo

Reference

Getting Started

Install visa:

  • Open your pubspec.yaml file and add visa: under dependencies.
  • From the terminal: Run flutter pub get.
  • Add the relevant import statements in the Dart code.
// Possible imports:
import 'package:visa/fb.dart';
import 'package:visa/google.dart';
import 'package:visa/github.dart';
import 'package:visa/discord.dart';
import 'package:visa/twitch.dart';
import 'package:visa/auth-data.dart';
import 'package:visa/engine/oauth.dart';
import 'package:visa/engine/simple-auth.dart';
import 'package:visa/engine/visa.dart';

Basic Usage

Step 1 - Get a Provider.

Implementing new providers is covered under Advanced Usage. There are 5 default OAuth providers at the moment:

  FacebookAuth()
  TwitchAuth()
  DiscordAuth()
  GithubAuth()
  GoogleAuth({ String personFields })

Create a new instance:

FacebookAuth fbAuth = FacebookAuth();
SimpleAuth visa = fbAuth.visa;

Step 2 - Authenticate.

As shown above, each provider contains a SimpleAuth instance called visa. The SimpleAuth class has only one public function: authenticate(). It takes in all the necessary OAuth credentials and returns a WebView that's been set up for authentication.

SimpleAuth.authenticate({ params })

WebView authenticate({
  bool newSession=false // If true, user has to reenter username and password even if they've logged in before
  String clientSecret, // Some providers (GitHub for instance) require the OAuth client secret (from developer portal).
  @required String clientID, // OAuth client ID (from developer portal)
  @required String redirectUri, // OAuth redirect url (from developer portal) 
  @required String state, // OAuth state string can be whatever you want.
  @required String scope, // OAuth scope (Check provider's API docs for allowed scopes)
  @required Function onDone, // Callback function which expects an AuthData object.
});

Here's how you would use this function:

import 'package:visa/auth-data.dart';
import 'package:visa/fb.dart';

class AuthPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      /// Simply Provide all the necessary credentials
      body: FacebookAuth().visa.authenticate(
          clientID: '139732240983759',
          redirectUri: 'https://www.e-oj.com/oauth',
          scope: 'public_profile,email',
          state: 'fbAuth',
          onDone: done
      )
    );
  }
}

In the sample above, the named parameter onDone is a callback which recieves a single arument: an AuthData object, which contains all the authentication info. We'll look at AuthData in the next section but here's how you would pass an AuthData object to the next screen via the onDone callback.

done(AuthData authData){
  print(authData);

  /// You can pass the [AuthData] object to a 
  /// post-authentication screen. It contaions 
  /// all the user and OAuth data collected during
  /// the authentication process. In this example,
  /// our post-authentication screen is "complete-profile".
  Navigator.pushReplacementNamed(
      context, '/complete-profile', arguments: authData
  );
}

Step 3 - Use AuthData.

The AuthData object contains all the information collected throughout the authentication process. It contains both user data and authentication metadata. As shown in the code sample above, this object is passed to the "authenticate" callback function. Let's have a look at it's structure:

class AuthData {
  final String userID; // User's profile id
  final String firstName; // User's first name
  final String lastName; // User's last name
  final String email; // User's email
  final String profileImgUrl; // User's profile image url
  final Map<String, dynamic> userJson; // Full returned user json
  final Map<String, String> response; // Full returned auth response.
  final String clientID; // OAuth client id
  final String accessToken; // OAuth access token
}

It provides shortcuts to access common user properties (userId, name, email, profile image) as well as the accessToken. The complete, returned user json can be accessed through the userJson property and you can access the full authentication response (the response in which we recieved an API access token) through the response property.

Step 4 - Rejoice!

You have successfully implemented third party auth in your app! you're one step closer to launch. Rejoice!

Advanced Usage

You might need an OAuth provider that's not currently supported. The Visa interface and the SimpleAuth class make this possible. Have a look at the Visa interface:

/// Visa interface
abstract class Visa{
  /// a [SimpleAuth] instance
  SimpleAuth visa;

  /// This function combines information
  /// from the user [json] and auth response [data]
  /// to build an [AuthData] object.
  AuthData authData(
      Map<String, dynamic> json,
      Map<String, String> data
  );
}

And here's the SimpleAuth constructor:

class SimpleAuth{

  /// Creates a new instance based on the given OAuth
  /// baseUrl and getAuthData function.
  const SimpleAuth ({
    @required this.baseUrl, @required this.getAuthData
  });
  
  
  final String baseUrl; // OAuth base url
  
  /// This function makes the necessary api calls to
  /// get a user's profile data. It accepts a single
  /// argument: a Map<String, String> containing the 
  /// full auth response including an api access token.
  /// An [AuthData] object is created from a combination 
  /// of the passed in auth response and the user 
  /// response returned from the api.
  ///
  /// @return [AuthData]
  final Function getAuthData; 
}

Creating an OAuth Provider

Adding a new provider simply means creating a new class that implements the visa interface. You can check out the source code for various implementations but here's the full Discord implementation as a reference.

Constructor:

/// Enables Discord [OAuth] authentication
class DiscordAuth implements Visa{
  // Oauth base url.
  final baseUrl = 'https://discord.com/api/oauth2/authorize';
  SimpleAuth visa;

  DiscordAuth(){
    visa = SimpleAuth(
        baseUrl: baseUrl,
        /// Sends a request to the user profile api
        /// endpoint. Returns an AuthData object.
        getAuthData: (Map <String, String> data) async {
          var token = data[OAuth.TOKEN_KEY];
          var baseProfileUrl = 'https://discord.com/api/users/@me';
          var profileResponse = await http.get(baseProfileUrl, headers: {
            'Authorization': 'Bearer $token',
          });
          var profileJson = json.decode(profileResponse.body);

          return authData(profileJson, data);
        }
    );
  }
}

authData function:

/// This function combines information
/// from the user [json] and auth response [data]
/// to build an [AuthData] object.
@override
AuthData authData(
    Map<String, dynamic> json,
    Map<String, String> data
){
  final String accessToken = data[OAuth.TOKEN_KEY];
  final String userId = json['id'] as String;
  final String avatar = json['avatar'] as String;
  final String profileImgUrl = 'https://cdn.discordapp.com/'
      'avatars/$userId/$avatar.png';

  return AuthData(
      clientID: data['clientID'],
      accessToken: accessToken,
      userID: userId,
      email: json['email'] as String,
      profileImgUrl: profileImgUrl,
      response: data,
      userJson: json
  );
}

Handling Intermediate Steps:

In some cases, the intitial request to an OAuth endpoint returns a code instead of an access token. This code has to be exchanged for an actual api access token. Github, for instance, uses this OAuth flow and the code above needs a few adjustments to accomodate the intermediate step. Let's take a look at the first few lines of the getAuthData function created in the Github constructor:

getAuthData(Map <String, String> data) async {
    // This function retrieves the access token and
    // adds it to the data HashMap.
    await _getToken(data);
    
    // We can now access the token
    var token = data[OAuth.TOKEN_KEY];
    
    // ... Make api requests/retrieve user data  with the token
}

_getToken makes the request to exchange an OAuth code for an access token.

  /// Github's [OAuth] endpoint returns a code
  /// which can be exchanged for a token. This
  /// function performs the exchange and adds the
  /// returned data to the response [data] map.
  _getToken(Map<String, String> data) async {
    var tokenEndpoint = 'https://github.com/login/oauth/access_token';
    var tokenResponse = await http.post(tokenEndpoint,
        headers: {'Accept': 'application/json',},
        body: {
          'client_id': data[OAuth.CLIENT_ID_KEY],
          'client_secret': data[OAuth.CLIENT_SECRET_KEY],
          'code': data[OAuth.CODE_KEY],
          'redirect_uri': data[OAuth.REDIRECT_URI_KEY],
          'state': data[OAuth.STATE_KEY]
        });

    var responseJson = json.decode(tokenResponse.body);
    var tokenTypeKey = 'token_type';

    data[OAuth.TOKEN_KEY] = responseJson[OAuth.TOKEN_KEY] as String;
    data[OAuth.SCOPE_KEY] = responseJson[OAuth.SCOPE_KEY] as String;
    data[tokenTypeKey] = responseJson[tokenTypeKey] as String;
  }
}

And that's how to handle intermedite OAuth steps! If you end up creating a new provider, feel free to open a PR and I'll be happy to add it to the project. Happy OAuthing!

Reference:

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].