1 module vibeauth.authenticators.oauth.PasswordGrantAccess;
2 
3 import vibeauth.authenticators.oauth.IGrantAccess;
4 import vibeauth.authenticators.oauth.AuthData;
5 import vibeauth.collections.usercollection;
6 
7 import std.datetime;
8 import std.array;
9 
10 import vibe.data.json;
11 
12 /// Grant user access based on username and password strings
13 final class PasswordGrantAccess : IGrantAccess {
14   private {
15     AuthData data;
16     UserCollection collection;
17   }
18 
19   /// setter for the authentication data
20   void authData(AuthData authData) {
21     this.data = authData;
22   }
23 
24   /// setter for the user collection
25   void userCollection(UserCollection userCollection) {
26     this.collection = userCollection;
27   }
28 
29   /// validate the authentication data
30   bool isValid() {
31     if(!collection.contains(data.username)) {
32       return false;
33     }
34 
35     if(!collection[data.username].isValidPassword(data.password)) {
36       return false;
37     }
38 
39     return true;
40   }
41 
42   /// Get the token Json response object
43   Json get() {
44     auto response = Json.emptyObject;
45 
46     if(!isValid) {
47       response["error"] = "Invalid password or username";
48       return response;
49     }
50 
51     auto now = Clock.currTime;
52 
53     auto user = collection[data.username];
54     foreach(token; user.getTokensByType("Bearer").array) {
55       if(token.expire < now) {
56         user.revoke(token.name);
57       }
58     }
59 
60     foreach(token; user.getTokensByType("Refresh").array) {
61       if(token.expire < now) {
62         user.revoke(token.name);
63       }
64     }
65 
66 
67     auto accessToken = collection.createToken(data.username, Clock.currTime + 3601.seconds, data.scopes, "Bearer");
68     auto refreshToken = collection.createToken(data.username, Clock.currTime + 4.weeks, data.scopes ~ [ "refresh" ], "Refresh");
69 
70     response["access_token"] = accessToken.name;
71     response["expires_in"] = (accessToken.expire - Clock.currTime).total!"seconds";
72     response["token_type"] = accessToken.type;
73     response["refresh_token"] = refreshToken.name;
74 
75     return response;
76   }
77 }