jaguar_auth 2.1.1 jaguar_auth: ^2.1.1 copied to clipboard
Authentication interceptors and helper functions for Jaguar
jaguar_auth #
Authentication interceptors and helper functions for Jaguar. This package builds on
Session
infrastructure provided by jaguar
.
This package provides three types of authentication:
And an Authorizer
User model #
AuthorizationUser
is the interface user models must
implement to work with Authorizer
and AuthModelManager
.
AuthorizationUser
demands that the model implements a
getter named authorizationId
that uniquely identifies
the user. This is usually stored in session to associate session with a
user.
Typically, user id, email or username is used as authorizationId
.
Example #
The user model User
uses user-id as authorizationId
.
Notice that User
implements AuthorizationUser
interface.
class User implements AuthorizationUser {
String id;
String username;
String password;
User(this.id, this.username, this.password);
String get authorizationId => id;
}
Model manager #
AuthModelManager
implements methods to fetch the user model
and also to authenticate the user against a password in a username-password
setup. This decouples data layer from the authentication logic. Authenticators and
Authorizers use AuthModelManager
to stay database
agnostic.
AuthModelManager
defines three methods:
fetchModelByAuthenticationId
fetchModelByAuthenticationId
is used byauthenticate
method to fetch user model by authentication id. Typically, username, email or even phone number is used as authentication id.fetchModelByAuthorizationId
fetchModelByAuthorizationId
is used byAuthorizer
to identify and fetch the user model from data store.authenticate
authenticate
method authenticates a user given their authentication id and a passphrase. Internally,authenticate
usesfetchModelByAuthenticationId
to fetch the user model by authentication id from the data storage. It then verifies that the pass phrase matches the one the model has.
Example #
/// Model manager to authenticate against a static list of user models
class WhiteListPasswordChecker implements AuthModelManager<User> {
/// User models to white list
final Map<String, User> models;
/// Password hasher
final Hasher hasher;
const WhiteListPasswordChecker(Map<String, User> models, {Hasher hasher})
: models = models ?? const {},
hasher = hasher ?? const NoHasher();
User authenticate(Context ctx, String username, String password) {
User model = fetchByAuthenticationId(ctx, username);
if (model == null) {
return null;
}
if (!hasher.verify(password, model.password)) {
return null;
}
return model;
}
User fetchByAuthenticationId(Context ctx, String authName) => models.values
.firstWhere((model) => model.username == authName, orElse: () => null);
User fetchByAuthorizationId(Context ctx, String sessionId) {
if (!models.containsKey(sessionId)) {
return null;
}
return models[sessionId];
}
}
final Map<String, User> kUsers = {
'0': new User('0', 'teja', 'word'),
'1': new User('1', 'kleak', 'pass'),
};
final WhiteListPasswordChecker kModelManager =
new WhiteListPasswordChecker(kUsers);
AuthModelManager implementations #
Several implementation of AuthModelManager
exist:
- MongoDB based
- PostgreSQL based
- Whitelist
Authorizer #
Authorizer
authorizes the requests. If the authorization fails,
it responds with a 401 http error.
If the authorization succeeds, it returns the user model of the authorized user.
Example #
/// Collection of routes students can also access
@Api(path: '/book')
class StudentRoutes extends Object with JsonRoutes {
JsonRepo get repo => jsonRepo;
@Get()
Future<Response<String>> getAllBooks(Context ctx) async {
// Authorize. Throws 401 http error, if authorization fails!
await Authorizer.authorize(ctx, kModelManager);
return toJson(_books.values);
}
@Get(path: '/:id')
Future<Response<String>> getBook(Context ctx) async {
// Authorize. Throws 401 http error, if authorization fails!
await Authorizer.authorize(ctx, kModelManager);
String id = ctx.pathParams.get('id');
Book book = _books[id];
return toJson(book);
}
}
Basic auth #
BasicAuth performs authentication based on basic authentication.
It expects base64 encoded "username:password" pair in "authorization" header with "Basic" scheme.
Example #
/// This route group contains login and logout routes
@Api()
class AuthRoutes extends Object with JsonRoutes {
JsonRepo get repo => jsonRepo;
@Post(path: '/login')
@WrapOne(basicAuth) // Wrap basic authenticator
Response<String> login(Context ctx) {
final User user = ctx.getInterceptorResult<User>(BasicAuth);
return toJson(user);
}
@Post(path: '/logout')
Future logout(Context ctx) async {
// Clear session data
(await ctx.session).clear();
}
static BasicAuth basicAuth(Context ctx) => new BasicAuth(kModelManager);
}
Example client #
TODO
Form auth #
An authenticator for standard username password form style login.
It expects a application/x-www-form-urlencoded
encoded body where the
username and password form fields must be called username
and password
respectively.
Example #
/// This route group contains login and logout routes
@Api()
class AuthRoutes extends Object with JsonRoutes {
JsonRepo get repo => jsonRepo;
@Post(path: '/login')
@WrapOne(formAuth)
Response<String> login(Context ctx) {
final User user = ctx.getInterceptorResult<User>(FormAuth);
return toJson(user);
}
@Post(path: '/logout')
Future logout(Context ctx) async {
// Clear session data
(await ctx.session).clear();
}
static FormAuth formAuth(Context ctx) => new FormAuth(kModelManager);
}
Example client #
TODO
Json auth #
An authenticator for standard username password login using ajax requests.
It expects a application/json
encoded body where the
username and password fields must be called username
and password
respectively.
Example #
/// This route group contains login and logout routes
@Api()
class AuthRoutes extends Object with JsonRoutes {
JsonRepo get repo => jsonRepo;
@Post(path: '/login')
@WrapOne(jsonAuth)
Response<String> login(Context ctx) {
final User user = ctx.getInterceptorResult<User>(JsonAuth);
return toJson(user);
}
@Post(path: '/logout')
Future logout(Context ctx) async {
// Clear session data
(await ctx.session).clear();
}
/// The authenticator
static JsonAuth jsonAuth(Context ctx) => new JsonAuth(kModelManager);
}
Example client #
TODO