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:
fetchModelByAuthenticationIdfetchModelByAuthenticationIdis used byauthenticatemethod to fetch user model by authentication id. Typically, username, email or even phone number is used as authentication id.fetchModelByAuthorizationIdfetchModelByAuthorizationIdis used byAuthorizerto identify and fetch the user model from data store.authenticateauthenticatemethod authenticates a user given their authentication id and a passphrase. Internally,authenticateusesfetchModelByAuthenticationIdto 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