diff --git a/.vscode/launch.json b/.vscode/launch.json index d6b9b242..27336ed7 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -6,7 +6,7 @@ "type": "dart-cli", "request": "launch", "cwd": "${workspaceRoot}", - "debugSettings": "${command.debugSettings}", + "debugSettings": "${command:debugSettings}", "program": "${workspaceRoot}/bin/server.dart", "args": [] }, @@ -15,7 +15,7 @@ "type": "dart-cli", "request": "launch", "cwd": "${workspaceRoot}", - "debugSettings": "${command.debugSettings}", + "debugSettings": "${command:debugSettings}", "program": "${workspaceRoot}/bin/multi_server.dart", "args": [] } diff --git a/lib/src/models/user.dart b/lib/src/models/user.dart index f7d4621d..2008f63d 100644 --- a/lib/src/models/user.dart +++ b/lib/src/models/user.dart @@ -3,7 +3,7 @@ library angel.models.user; import 'package:angel_framework/common.dart'; class User extends Model { - String email, username, password; + String email, username, password, salt; final List roles = []; User( @@ -11,6 +11,7 @@ class User extends Model { this.email, this.username, this.password, + this.salt, Iterable roles: const []}) { this.id = id; this.roles.addAll(roles ?? []); diff --git a/lib/src/routes/controllers/auth.dart b/lib/src/routes/controllers/auth.dart index 81645c1e..2221f30d 100644 --- a/lib/src/routes/controllers/auth.dart +++ b/lib/src/routes/controllers/auth.dart @@ -13,12 +13,15 @@ class AuthController extends Controller { /// Attempt to log a user in LocalAuthVerifier localVerifier(UserService userService) { return (String username, String password) async { - List users = await userService.index({'query':{'username': username}}); + List users = await userService.index({ + 'query': {'username': username} + }); if (users.isNotEmpty) { - var hash = hashPassword(password); - return users.firstWhere((user) => user.password == hash, - orElse: () => null); + return users.firstWhere((user) { + var hash = hashPassword(password, user.salt, app.jwt_secret); + return user.username == username && user.password == hash; + }, orElse: () => null); } }; } @@ -29,8 +32,8 @@ class AuthController extends Controller { auth = new AngelAuth(jwtKey: app.jwt_secret) ..serializer = serializer ..deserializer = deserializer - ..strategies.add( - new LocalAuthStrategy(localVerifier(app.container.make(UserService)))); + ..strategies.add(new LocalAuthStrategy( + localVerifier(app.container.make(UserService)))); await super.call(app); await app.configure(auth); diff --git a/lib/src/services/user.dart b/lib/src/services/user.dart index 27169829..79d31fc4 100644 --- a/lib/src/services/user.dart +++ b/lib/src/services/user.dart @@ -1,6 +1,7 @@ import 'package:angel_common/angel_common.dart'; import 'package:crypto/crypto.dart' show sha256; import 'package:mongo_dart/mongo_dart.dart'; +import 'package:random_string/random_string.dart' as rs; import '../models/user.dart'; import '../validators/user.dart'; export '../models/user.dart'; @@ -15,14 +16,18 @@ configureServer(Db db) { service.beforeCreated ..listen(validateEvent(CREATE_USER)) ..listen((e) { - e.data['password'] = hashPassword(e.data['password']); + var salt = rs.randomAlphaNumeric(12); + e.data + ..['password'] = + hashPassword(e.data['password'], salt, app.jwt_secret) + ..['salt'] = salt; }); }; } /// SHA-256 hash any string, particularly a password. -String hashPassword(String password) => - sha256.convert(password.codeUnits).toString(); +String hashPassword(String password, String salt, String pepper) => + sha256.convert(('$salt:$password:$pepper').codeUnits).toString(); /// Manages users. /// diff --git a/lib/src/validators/user.dart b/lib/src/validators/user.dart index e094496b..1d8bf2fd 100644 --- a/lib/src/validators/user.dart +++ b/lib/src/validators/user.dart @@ -7,4 +7,5 @@ final Validator USER = new Validator({ }); final Validator CREATE_USER = USER.extend({}) - ..requiredFields.addAll(['email', 'username', 'password']); + ..requiredFields.addAll(['email', 'username', 'password']) + ..forbiddenFields.addAll(['salt', 'roles']);