angel_auth_oauth2 2.0.0+1

  • README.md
  • CHANGELOG.md
  • Example
  • Installing
  • Versions
  • 74

auth_oauth2

Pub

package:angel_auth strategy for OAuth2 login, i.e. Facebook or Github.

Usage

First, create an options object:

configureServer(Angel app) async {
  // Load from a Map, i.e. app config:
  var opts = new AngelOAuth2Options.fromJson(map);
  
  // Create in-place:
  var opts = const AngelAuthOAuth2Options(
      callback: '<callback-url>',
      key: '<client-id>',
      secret: '<client-secret>',
      authorizationEndpoint: '<authorization-endpoint>',
      tokenEndpoint: '<access-token-endpoint>');
}

After getting authenticated against the remote server, we need to be able to identify users within our own application. Use an OAuth2Verifier to associate remote users with local users.

/// You might use a pure function to create a verifier that queries a
/// given service.
OAuth2Verifier oauth2verifier(Service userService) {
  return (oauth2.Client client) async {
     var response = await client.get('https://api.github.com/user');
     var ghUser = JSON.decode(response.body);
     var id = ghUser['id'];
 
     Iterable<Map> matchingUsers = await userService.index({
       'query': {'githubId': id}
     });
 
     if (matchingUsers.isNotEmpty) {
       // Return the corresponding user, if it exists
       return User.parse(matchingUsers.firstWhere((u) => u['githubId'] == id));
     } else {
       // Otherwise,create a user
       return await userService.create({'githubId': id}).then(User.parse);
     }
   };
}

Now, initialize an OAuth2Strategy, using the options and verifier. You'll also need to provide a name for this instance of the strategy. Consider using the name of the remote authentication provider (ex. facebook).

configureServer(Angel app) {
  // ...
  var oauthStrategy =
    new OAuth2Strategy('github', OAUTH2_CONFIG, oauth2Verifier(app.service('users')));
}

Lastly, connect it to an AngelAuth instance, and wire it up to an Angel server. Set up two routes:

  1. Redirect users to the external provider
  2. Acts as a callback and handles an access code

In the case of the callback route, you may want to display an HTML page that closes a popup window. In this case, use confirmPopupAuthentication, which is bundled with package:angel_auth, as a callback function:

configureServer(Angel app) async {
  // ...
  var auth = new AngelAuth();
  auth.strategies['github'] = oauth2Strategy;
  
  // Redirect
  app.get('/auth/github', auth.authenticate('github'));
  
  // Callback
  app.get('/auth/github/callback', auth.authenticate(
    'github',
    new AngelAuthOptions(callback: confirmPopupAuthentication())
  ));
  
  // Connect the plug-in!!!
  await app.configure(auth);
}

Custom Scope Delimiter

This package should work out-of-the-box for most OAuth2 providers, such as Github or Dropbox. However, if your OAuth2 scopes are separated by a delimiter other than the default (' '), you can add it in the AngelOAuth2Options constructor:

configureServer(Angel app) async {
  var opts = const AngelOAuth2Options(
    // ...
    delimiter: ','
  );
}

Handling non-JSON responses

Many OAuth2 providers do not follow the specification, and do not return application/json responses.

You can add a getParameters callback to parse the contents of any arbitrary response:

var opts = const AngelOAuth2Options(
    // ...
    getParameters: (contentType, body) {
      if (contentType.type == 'application') {
        if (contentType.subtype == 'x-www-form-urlencoded')
          return Uri.splitQueryString(body);
        else if (contentType.subtype == 'json') return JSON.decode(body);
      }

      throw new FormatException('Invalid content-type $contentType; expected application/x-www-form-urlencoded or application/json.');
    }
);

2.0.0+1

  • Meta update to improve Pub score.

2.0.0

  • Angel 2 + Dart 2 updates.

1.0.2

Added getParameters to AngelOAuth2Options.

example/main.dart

import 'dart:convert';
import 'dart:io';
import 'package:angel_auth/angel_auth.dart';
import 'package:angel_framework/angel_framework.dart';
import 'package:angel_auth_oauth2/angel_auth_oauth2.dart';
import 'package:logging/logging.dart';
import 'package:oauth2/oauth2.dart' as oauth2;

final AngelAuthOAuth2Options oAuth2Config = new AngelAuthOAuth2Options(
    callback: 'http://localhost:3000/auth/github/callback',
    key: '6caeaf5d4c04936ec34f',
    secret: '178360518cf9de4802e2346a4b6ebec525dc4427',
    authorizationEndpoint: 'http://github.com/login/oauth/authorize',
    tokenEndpoint: 'https://github.com/login/oauth/access_token',
    getParameters: (contentType, body) {
      if (contentType.type == 'application') {
        if (contentType.subtype == 'x-www-form-urlencoded')
          return Uri.splitQueryString(body);
        else if (contentType.subtype == 'json')
          return (json.decode(body) as Map).cast<String, String>();
      }

      throw new FormatException(
          'Invalid content-type $contentType; expected application/x-www-form-urlencoded or application/json.');
    });

main() async {
  var app = new Angel();
  app.use('/users', new MapService());

  var auth =
      new AngelAuth<User>(jwtKey: 'oauth2 example secret', allowCookie: false);

  auth.deserializer =
      (id) => app.service('users').read(id).then((u) => User.parse(u as Map));

  auth.serializer = (User user) async => user.id;

  auth.strategies['github'] = new OAuth2Strategy(
    oAuth2Config,
    (oauth2.Client client) async {
      var response = await client.get('https://api.github.com/user');
      var ghUser = json.decode(response.body);
      var id = ghUser['id'];

      Iterable<Map> matchingUsers = await app.service('users').index({
        'query': {'githubId': id}
      });

      if (matchingUsers.isNotEmpty) {
        // Return the corresponding user, if it exists
        return User.parse(matchingUsers.firstWhere((u) => u['githubId'] == id));
      } else {
        // Otherwise,create a user
        return await app
            .service('users')
            .create({'githubId': id}).then((u) => User.parse(u as Map));
      }
    },
  );

  app.get('/auth/github', auth.authenticate('github'));
  app.get(
      '/auth/github/callback',
      auth.authenticate('github',
          new AngelAuthOptions(callback: (req, res, jwt) async {
        // In real-life, you might include a pop-up callback script.
        //
        // Use `confirmPopupAuthentication`, which is bundled with
        // `package:angel_auth`.
        res.write('Your JWT: $jwt');
      })));

  await app.configure(auth.configureServer);

  app.logger = new Logger('angel')..onRecord.listen(print);

  var http = new AngelHttp(app);
  var server = await http.startServer(InternetAddress.loopbackIPv4, 3000);
  var url = 'http://${server.address.address}:${server.port}';
  print('Listening on $url');
  print('View user listing: $url/users');
  print('Sign in via Github: $url/auth/github');
}

class User extends Model {
  @override
  String id;
  int githubId;

  User({this.id, this.githubId});

  static User parse(Map map) =>
      new User(id: map['id'] as String, githubId: map['github_id'] as int);

  Map<String, dynamic> toJson() => {'id': id, 'github_id': githubId};
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  angel_auth_oauth2: ^2.0.0+1

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter packages get

Alternatively, your editor might support pub get or flutter packages get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:angel_auth_oauth2/angel_auth_oauth2.dart';
  
Version Uploaded Documentation Archive
2.0.0+1 Sep 12, 2018 Go to the documentation of angel_auth_oauth2 2.0.0+1 Download angel_auth_oauth2 2.0.0+1 archive
2.0.0 Sep 12, 2018 Go to the documentation of angel_auth_oauth2 2.0.0 Download angel_auth_oauth2 2.0.0 archive
1.0.2 Mar 30, 2018 Go to the documentation of angel_auth_oauth2 1.0.2 Download angel_auth_oauth2 1.0.2 archive
1.0.1 Jun 3, 2017 Go to the documentation of angel_auth_oauth2 1.0.1 Download angel_auth_oauth2 1.0.1 archive
1.0.0 Feb 23, 2017 Go to the documentation of angel_auth_oauth2 1.0.0 Download angel_auth_oauth2 1.0.0 archive
0.0.0 Jan 12, 2017 Go to the documentation of angel_auth_oauth2 0.0.0 Download angel_auth_oauth2 0.0.0 archive
Popularity:
Describes how popular the package is relative to other packages. [more]
49
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
74
Learn more about scoring.

We analyzed this package on Dec 5, 2018, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.1.0
  • pana: 0.12.7

Platforms

Detected platforms: Flutter, other

Primary library: package:angel_auth_oauth2/angel_auth_oauth2.dart with components: io.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.0.0-dev <3.0.0
angel_auth ^2.0.0 2.0.2
angel_framework ^2.0.0-alpha 2.0.0-alpha.14
angel_validate ^2.0.0-alpha 2.0.0
http_parser ^3.0.0 3.1.3
oauth2 ^1.0.0 1.2.3
Transitive dependencies
angel_container 1.0.0
angel_http_exception 1.0.0+3
angel_model 1.0.0+1
angel_route 3.0.0
async 2.0.8
body_parser 1.1.1
charcode 1.1.2
code_buffer 1.0.1
collection 1.14.11
combinator 1.0.0+3
convert 2.0.2
crypto 2.0.6
dart2_constant 1.0.2+dart2
file 5.0.6
http 0.12.0
http2 0.1.9
http_server 0.9.8+1
intl 0.15.7
matcher 0.12.4
merge_map 1.0.1
meta 1.1.6
mime 0.9.6+2
mock_request 1.0.4
path 1.6.2
quiver 2.0.1
source_span 1.4.1
stack_trace 1.9.3
string_scanner 1.0.4
tuple 1.0.2
typed_data 1.1.6
uuid 1.0.3
Dev dependencies
logging ^0.11.0 0.11.3+2