private async Task <IActionResult> AuthoriseUser(string authToken, AuthType authType, string firstName, string lastName) { if (authType == AuthType.Unknown) { return(BadRequest()); } var metadata = await tokenUtil.GetMetadataForToken(authToken, authType).ConfigureAwait(false); if (metadata == null || string.IsNullOrWhiteSpace(metadata.AuthIdentifier)) { return(BadRequest()); } var user = await users.FetchUserForAuthIdentifier(metadata.AuthIdentifier, authType).ConfigureAwait(false); if (user.IsFailure) { return(StatusCode(500)); } if (user.Value.HasValue) { var userId = user.Value.Value.UserId; if (string.IsNullOrWhiteSpace(user.Value.Value.ExternalPaymentProcessorId)) { try { var billingId = await billingManager.CreateCustomer(user.Value.Value).ConfigureAwait(false); await users.UpdateUser(new UserPatch { ResourceId = userId, ExternalPaymentProcessorId = new PatchOperation <string> { Operation = OperationKind.Update, Value = billingId } }).ConfigureAwait(false); } catch (Exception) { return(StatusCode(500)); } } if (!string.IsNullOrWhiteSpace(firstName) || !string.IsNullOrWhiteSpace(lastName)) { await users.UpdateUser(new UserPatch { ResourceId = userId, FirstName = new PatchOperation <string> { Operation = OperationKind.Update, Value = firstName ?? "Anonymous" }, LastName = new PatchOperation <string> { Operation = OperationKind.Update, Value = lastName }, }).ConfigureAwait(false); } var existingSession = await userSessions.FetchUserSessionAndUserFromToken(authToken, (int)authType) .Ensure(s => s.HasValue, "Data found") .OnSuccess(s => s.Value) .ConfigureAwait(false); if (existingSession.IsFailure) { var session = new UserSession { AuthToken = authToken, UserId = userId, TokenType = (int)authType, AuthTokenExpiry = metadata.Expiry }; var sessionId = await userSessions.CreateUserSession(session).ConfigureAwait(false); if (sessionId.IsFailure) { return(StatusCode(500)); } } } else { var newUser = new User { IsVerified = true, WantAdvertising = false, RegistrationId = tokenUtil.GenerateToken(), FirstName = firstName ?? "Anonymous", LastName = lastName }; switch (authType) { case AuthType.Apple: newUser.AppleUserIdentifier = metadata.AuthIdentifier; break; case AuthType.Google: newUser.GoogleUserIdentifier = metadata.AuthIdentifier; break; case AuthType.Facebook: newUser.FacebookUserIdentifier = metadata.AuthIdentifier; break; case AuthType.Unknown: break; } var result = await users.CreateUser(newUser).ConfigureAwait(false); if (result.IsFailure) { return(StatusCode(500)); } var userId = result.Value.Value; try { var billingId = await billingManager.CreateCustomer(newUser).ConfigureAwait(false); await users.UpdateUser(new UserPatch { ResourceId = userId, ExternalPaymentProcessorId = new PatchOperation <string> { Operation = OperationKind.Update, Value = billingId } }).ConfigureAwait(false); } catch (Exception) { return(StatusCode(500)); } var existingSession = await userSessions.FetchUserSessionAndUserFromToken(authToken, (int)authType) .Ensure(s => s.HasValue, "Data found") .OnSuccess(s => s.Value) .ConfigureAwait(false); if (existingSession.IsFailure) { var session = new UserSession { AuthToken = authToken, UserId = userId, TokenType = (int)authType, AuthTokenExpiry = metadata.Expiry }; var sessionId = await userSessions.CreateUserSession(session).ConfigureAwait(false); if (sessionId.IsFailure) { return(StatusCode(500)); } } } return(Ok()); }
private async Task<AuthorisationResult> EnforceRBACRequirements(AuthContext authContext, Microsoft.AspNetCore.Routing.RouteData routeData) { var userType = authContext.UserType; // Grab the route name via the [ActionName(...)] annotation on a controller method. // If you don't annotate your methods, or have not configured this route as authenticated, we won't apply any auth restrictions. var routeName = (string)routeData.Values["action"]; if (routeName == null || !settings.Meta.AuthRequirements.ContainsKey(routeName)) { return AuthorisationResult.InjectAndContinue; } var requirements = settings.Meta.AuthRequirements[routeName]; Maybe<Employee> employee = null; Maybe<EmployeeRole> employeeRole = null; Maybe<User> user = null; if (userType != settings.Meta.AuthRequirements[routeName].UserType && UserType.Any != settings.Meta.AuthRequirements[routeName].UserType) { return AuthorisationResult.AbortUnauthorised; } if (authContext.AuthToken.HasNoValue) { return AuthorisationResult.AbortUnauthorised; } var authToken = authContext.AuthToken.Value; // Depending on the session type, attempt to fetch the equivalent model (User or Employee). if (userType == UserType.Employee) { employee = (await employeeSessions.FetchEmployeeSessionAndEmployeeFromToken(authToken).ConfigureAwait(false)) .OnBoth(x => x.IsSuccess ? x.Value : Maybe<Employee>.None ); if (employee.HasNoValue) { return AuthorisationResult.AbortUnauthorised; } // For employees, their permissions are scoped to an employee role. First we fetch the role. employeeRole = (await employeeRoles.FetchEmployeeRole(employee.Value.RoleId).ConfigureAwait(false)) .OnBoth(x => x.IsSuccess ? x.Value : Maybe<EmployeeRole>.None ); // If the employee role wasn't found but the route didn't require any permissions, we let them through. if (employeeRole.HasNoValue && RouteRequiresAtLeastOnePermission(requirements)) { return AuthorisationResult.AbortUnauthorised; } // Verify each of the role permissions in turn, if one is missing and the route requires it, deny access. if (!RoleHasCorrectPermissions(employeeRole.Value, requirements)) { return AuthorisationResult.AbortUnauthorised; } } else if (userType == UserType.User) { user = (await userSessions.FetchUserSessionAndUserFromToken(authToken, (int)authContext.AuthType).ConfigureAwait(false)) .OnBoth(x => x.IsSuccess ? x.Value : Maybe<User>.None ); if (user.HasNoValue) { return AuthorisationResult.AbortUnauthorised; } } // After verifying the user's permissions, update the context with relevant user data and continue. authContext.Employee = employee; authContext.EmployeeRole = employeeRole; authContext.User = user; return AuthorisationResult.Continue; }