public async Task <UserRefToken> GetUserRefToken(IWebRequest req)
        {
            var          authentication = req.GetAuthenticationHeaderValue();
            UserRefToken userRefToken   = await this.AuthenticateAsync(authentication?.Scheme, authentication?.Parameter) as UserRefToken;

            if (userRefToken == null)
            {
                throw new UnauthorizedException();
            }
            return(userRefToken);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Validates the auth token id returning an <see cref="AuthToken"/> instance
        /// </summary>
        /// <param name="authType"></param>
        /// <param name="authValue"></param>
        /// <returns>An <see cref="AuthToken"/> instance</returns>
        public async Task <AuthToken> AuthenticateAsync(string authType, string authValue)
        {
            List <string> fieldList = new List <string>();

            if (!string.IsNullOrEmpty(this.authTokenIdFieldName))
            {
                fieldList.Add($"at.{ this.authTokenIdFieldName}");
            }
            if (!string.IsNullOrEmpty(this.authTokenTableUserIdFieldName))
            {
                fieldList.Add($"at.{ this.authTokenTableUserIdFieldName}");
            }
            if (!string.IsNullOrEmpty(this.userTableAccountIdFieldName))
            {
                fieldList.Add($"u.{ this.userTableAccountIdFieldName}");
            }
            if (!string.IsNullOrEmpty(this.userTableUsernameFieldName))
            {
                fieldList.Add($"u.{ this.userTableUsernameFieldName}");
            }
            if (!string.IsNullOrEmpty(this.userTableRoleFieldName))
            {
                fieldList.Add($"u.{ this.userTableRoleFieldName}");
            }
            if (!string.IsNullOrEmpty(this.authTokenTableExpiresAtFieldName))
            {
                fieldList.Add($"at.{ this.authTokenTableExpiresAtFieldName}");
            }
            Dict authTokenDict = await this.database.SelectRowAsync($"SELECT {string.Join(",", fieldList)} FROM {this.authTokenTableName} at INNER JOIN {this.userTableName} u ON at.user_id=u.id WHERE at.id=@authTokenId", new {
                authTokenId = authValue
            });

            logger.Debug($"Authenticate():authTokenDict={authTokenDict}");
            if (authTokenDict == null)
            {
                throw new UnauthorizedException();
            }

            var authToken = UserRefToken.FromDict(authTokenDict, this.authTokenIdFieldName, this.authTokenTableUserIdFieldName, this.userTableUsernameFieldName, this.userTableRoleFieldName, this.userTableAccountIdFieldName, this.authTokenTableExpiresAtFieldName);

            logger.Debug($"Authenticate():authToken.expiresAt={authToken.expiresAt}");
            if (authToken.expiresAt == DateTime.MinValue || authToken.expiresAt < DateTime.Now)
            {
                throw new UnauthorizedException();
            }

            return(authToken);
        }
        /// <summary>
        /// Registers a new user
        /// </summary>
        /// <param name="input"></param>
        /// <param name="notifyData"></param>
        /// <returns></returns>
        public async Task <UserRefToken> RegisterAsync(dynamic input, Dict notifyData = null)
        {
            Dict registration = this.ConvertInputToDict(input);

            // Handle registering an anonymous user
            string userId    = registration.GetAs("user_id", (string)null);
            string accountId = null;

            logger.Trace($"RegisterAsync():userId={userId}");
            if (!string.IsNullOrEmpty(userId))
            {
                accountId = await this.database.SelectValueAsync <string>($"SELECT account_id FROM {this.userTableName}", userId);
            }
            if (string.IsNullOrEmpty(accountId))
            {
                userId = null;
            }

            // Validate username
            string username = this.usernameFieldValidator.Validate(registration?.GetAs(this.userTableUsernameFieldName, (string)null));

            logger.Trace($"RegisterAsync():username={username}");
            Dict existingUserByUsername = await this.database.SelectRowAsync(this.userTableName, new Dict {
                { this.userTableUsernameFieldName, username }
            });

            if (existingUserByUsername != null)
            {
                throw new Exception("Username '" + username + "' is unavailable");
            }

            // Validate password
            string password = this.passwordFieldValidator.Validate(registration?.GetAs("password", (string)null));

            // Validate email and phone
            string email = this.emailFieldValidator.Validate(registration?.GetAs(this.userTableEmailFieldName, (string)null));
            string phone = this.phoneFieldValidator.Validate(registration?.GetAs(this.userTablePhoneFieldName, (string)null));

            // Validate first and last name
            string firstName = this.nameFieldValidator.Validate(registration?.GetAs(this.userTableFirstNameFieldName, (string)null));
            string lastName  = this.nameFieldValidator.Validate(registration?.GetAs(this.userTableLastNameFieldName, (string)null));

            string role = string.IsNullOrEmpty(this.userTableRoleFieldName) ? this.defaultRole : registration?.GetAs(this.userTableRoleFieldName, this.defaultRole);

            // Create salt and password hash
            string salt         = Guid.NewGuid().ToString();
            string passwordHash = $"{salt} {password}".Hash();

            // Create account
            using (ITransaction transaction = await this.database.BeginTransactionAsync()) {
                if (string.IsNullOrEmpty(accountId))
                {
                    Dict extraAccountInfo = this.getExtraAccountInfo == null ? null : this.getExtraAccountInfo(registration);
                    accountId = await transaction.InsertAsync <string>(this.accountTableName, extraAccountInfo);

                    if (this.onRegisterAccount != null)
                    {
                        Dict registerAccount = new Dict(extraAccountInfo)
                        {
                            ["id"] = accountId
                        };
                        transaction.OnCommit(async() => {
                            try {
                                await this.onRegisterAccount(registerAccount);
                            }
                            catch (Exception e) {
                                logger.Debug(e);
                            }
                        });
                    }
                }

                // Create user record
                Dict user = new Dict {
                    { this.userTableAccountIdFieldName, accountId },
                    { this.userTableUsernameFieldName, username },
                    { this.userTableSaltFieldName, salt },
                    { this.userTablePasswordHashFieldName, passwordHash },
                    { this.userTableEmailFieldName, email },
                    { this.userTablePhoneFieldName, phone },
                    { this.userTableFirstNameFieldName, firstName },
                    { this.userTableLastNameFieldName, lastName },
                };
                if (!string.IsNullOrEmpty(this.userTableRoleFieldName) && !string.IsNullOrEmpty(this.defaultRole))
                {
                    user[this.userTableRoleFieldName] = role;
                }
                Dict extraUserInfo = this.getExtraUserInfo == null ? null : this.getExtraUserInfo(registration);
                if (extraUserInfo != null)
                {
                    user.UpdateFrom(extraUserInfo);
                }
                if (string.IsNullOrEmpty(userId))
                {
                    userId = await transaction.InsertAsync <string>(this.userTableName, user);
                }
                else
                {
                    user[this.userTableIdFieldName] = userId;
                    await transaction.UpdateAsync(this.userTableName, user);
                }

                if (this.onRegisterUser != null)
                {
                    transaction.OnCommit(async() => {
                        var registerUser = new Dict {
                            { this.userTableAccountIdFieldName, accountId },
                            { this.userTableUsernameFieldName, username },
                            { this.userTableEmailFieldName, email },
                            { this.userTablePhoneFieldName, phone },
                            { this.userTableFirstNameFieldName, firstName },
                            { this.userTableLastNameFieldName, lastName },
                        };
                        try {
                            if (notifyData != null)
                            {
                                registerUser.UpdateFrom(notifyData);
                            }
                            await this.onRegisterUser(registerUser);
                        }
                        catch (Exception e) {
                            logger.Debug(e);
                        }
                    });
                }

                UserRefToken userRefToken = await this.CreateUserRefTokenAsync(transaction, userId, username, role, accountId);

                await transaction.CommitAsync();

                return(userRefToken);
            }
        }