public bool TryAuthorize(RavenBaseApiController controller, out HttpResponseMessage msg)
        {
            var requestUrl = controller.GetRequestUrl();

            if (NeverSecret.IsNeverSecretUrl(requestUrl))
            {
                msg = controller.GetEmptyMessage();
                return(true);
            }

            //CORS pre-flight (ignore creds if using cors).
            if (Settings.AccessControlAllowOrigin.Count > 0 && controller.InnerRequest.Method.Method == "OPTIONS")
            {
                msg = controller.GetEmptyMessage();
                return(true);
            }

            var oneTimeToken = controller.GetHeader("Single-Use-Auth-Token");

            if (string.IsNullOrEmpty(oneTimeToken) == false)
            {
                return(TryAuthorizeSingleUseAuthToken(controller, oneTimeToken, out msg));
            }

            var authHeader            = controller.GetHeader("Authorization");
            var hasApiKey             = "True".Equals(controller.GetHeader("Has-Api-Key"), StringComparison.CurrentCultureIgnoreCase);
            var hasOAuthTokenInCookie = controller.HasCookie("OAuth-Token");

            if (hasApiKey || hasOAuthTokenInCookie ||
                string.IsNullOrEmpty(authHeader) == false && authHeader.StartsWith("Bearer "))
            {
                return(oAuthRequestAuthorizer.TryAuthorize(controller, hasApiKey, IgnoreDb.Urls.Contains(requestUrl), out msg));
            }
            return(windowsRequestAuthorizer.TryAuthorize(controller, IgnoreDb.Urls.Contains(requestUrl), out msg));
        }
        private bool TryAuthorizeSingleUseAuthToken(RavenBaseApiController controller, string token, out HttpResponseMessage msg)
        {
            if (controller.WasAlreadyAuthorizedUsingSingleAuthToken)
            {
                msg = controller.GetEmptyMessage();
                return(true);
            }

            object         result;
            HttpStatusCode statusCode;
            IPrincipal     user;
            var            success = TryAuthorizeSingleUseAuthToken(token, controller.TenantName, out result, out statusCode, out user);

            controller.User = user;
            if (success == false)
            {
                msg = controller.GetMessageWithObject(result, statusCode);
            }
            else
            {
                msg = controller.GetEmptyMessage();
            }

            controller.WasAlreadyAuthorizedUsingSingleAuthToken = success;
            return(success);
        }
예제 #3
0
        public bool TryAuthorize(RavenBaseApiController controller, out HttpResponseMessage msg)
		{
			var requestUrl = controller.GetRequestUrl();
			if (NeverSecret.IsNeverSecretUrl(requestUrl))
			{
				msg = controller.GetEmptyMessage();
				return true;
			}

			//CORS pre-flight (ignore creds if using cors).
			if (!String.IsNullOrEmpty(Settings.AccessControlAllowOrigin) && controller.InnerRequest.Method.Method == "OPTIONS")
			{
				msg = controller.GetEmptyMessage();
				return true;
			}

			var oneTimeToken = controller.GetHeader("Single-Use-Auth-Token");
			if (string.IsNullOrEmpty(oneTimeToken) == false)
			{
				return TryAuthorizeSingleUseAuthToken(controller, oneTimeToken, out msg);
			}

			var authHeader = controller.GetHeader("Authorization");
			var hasApiKey = "True".Equals(controller.GetHeader("Has-Api-Key"), StringComparison.CurrentCultureIgnoreCase);
			var hasOAuthTokenInCookie = controller.HasCookie("OAuth-Token");
			if (hasApiKey || hasOAuthTokenInCookie ||
				string.IsNullOrEmpty(authHeader) == false && authHeader.StartsWith("Bearer "))
			{
				return oAuthRequestAuthorizer.TryAuthorize(controller, hasApiKey, IgnoreDb.Urls.Contains(requestUrl), out msg);
			}
			return windowsRequestAuthorizer.TryAuthorize(controller, IgnoreDb.Urls.Contains(requestUrl), out msg);
		}
예제 #4
0
        HttpResponseMessage WriteAuthorizationChallenge(RavenBaseApiController controller, int statusCode, string error, string errorDescription)
        {
            var msg = controller.GetEmptyMessage();
            var systemConfiguration = controller.SystemConfiguration;

            if (string.IsNullOrEmpty(systemConfiguration.OAuthTokenServer) == false)
            {
                if (systemConfiguration.UseDefaultOAuthTokenServer == false)
                {
                    controller.AddHeader("OAuth-Source", systemConfiguration.OAuthTokenServer, msg);
                }
                else
                {
                    controller.AddHeader("OAuth-Source", new UriBuilder(systemConfiguration.OAuthTokenServer)
                    {
                        Scheme = controller.InnerRequest.RequestUri.Scheme,
                        Host   = controller.InnerRequest.RequestUri.Host,
                        Port   = controller.InnerRequest.RequestUri.Port,
                    }.Uri.ToString(), msg);
                }
            }
            msg.StatusCode = (HttpStatusCode)statusCode;

            msg.Headers.Add("WWW-Authenticate", string.Format("Bearer realm=\"Raven\", error=\"{0}\",error_description=\"{1}\"", error, errorDescription));
            msg.Headers.Add("Access-Control-Expose-Headers", "WWW-Authenticate, OAuth-Source");
            return(msg);
        }
예제 #5
0
        private static HttpResponseMessage ProvideDebugAuthInfo(RavenBaseApiController controller, object msg)
        {
            string debugAuth = controller.GetQueryStringValue("debug-auth");

            if (debugAuth == null)
            {
                return(controller.GetEmptyMessage());
            }

            bool shouldProvideDebugAuthInformation;

            if (bool.TryParse(debugAuth, out shouldProvideDebugAuthInformation) && shouldProvideDebugAuthInformation)
            {
                return(controller.GetMessageWithObject(msg));
            }

            return(controller.GetEmptyMessage());
        }
        private bool TryAuthorizeSingleUseAuthToken(RavenBaseApiController controller, string token, out HttpResponseMessage msg)
        {
            OneTimeToken value;

            if (singleUseAuthTokens.TryRemove(token, out value) == false)
            {
                msg = controller.GetMessageWithObject(
                    new
                {
                    Error = "Unknown single use token, maybe it was already used?"
                }, HttpStatusCode.Forbidden);
                return(false);
            }

            if (string.Equals(value.DatabaseName, controller.TenantName, StringComparison.InvariantCultureIgnoreCase) == false &&
                (value.DatabaseName == "<system>" && controller.TenantName == null) == false)
            {
                msg = controller.GetMessageWithObject(
                    new
                {
                    Error = "This single use token cannot be used for this database"
                }, HttpStatusCode.Forbidden);
                return(false);
            }
            if ((SystemTime.UtcNow - value.GeneratedAt).TotalMinutes > 2.5)
            {
                msg = controller.GetMessageWithObject(
                    new
                {
                    Error = "This single use token has expired"
                }, HttpStatusCode.Forbidden);
                return(false);
            }

            if (value.User != null)
            {
                CurrentOperationContext.Headers.Value[Constants.RavenAuthenticatedUser] = value.User.Identity.Name;
            }

            CurrentOperationContext.User.Value = value.User;
            controller.User = value.User;
            msg             = controller.GetEmptyMessage();
            return(true);
        }
예제 #7
0
        private bool TryAuthorizeSingleUseAuthToken(RavenBaseApiController controller, string token, out HttpResponseMessage msg)
        {
            if (controller.WasAlreadyAuthorizedUsingSingleAuthToken)
            {
                msg = controller.GetEmptyMessage();
                return(true);
            }

            object         result;
            HttpStatusCode statusCode;
            IPrincipal     user;
            var            resourceName = controller.ResourceName == null ? null : controller.ResourcePrefix + controller.ResourceName;
            var            success      = TryAuthorizeSingleUseAuthToken(token, resourceName, out result, out statusCode, out user);

            controller.User = user;
            msg             = success == false?controller.GetMessageWithObject(result, statusCode) : controller.GetEmptyMessage();

            controller.WasAlreadyAuthorizedUsingSingleAuthToken = success;
            return(success);
        }
예제 #8
0
        HttpResponseMessage WriteAuthorizationChallenge(RavenBaseApiController controller, int statusCode, string error, string errorDescription)
		{
			var msg = controller.GetEmptyMessage();
			var systemConfiguration = controller.SystemConfiguration;
			if (string.IsNullOrEmpty(systemConfiguration.OAuthTokenServer) == false)
			{
				if (systemConfiguration.UseDefaultOAuthTokenServer == false)
				{
					controller.AddHeader("OAuth-Source", systemConfiguration.OAuthTokenServer, msg);
				}
				else
				{
					controller.AddHeader("OAuth-Source", new UriBuilder(systemConfiguration.OAuthTokenServer)
					{
						Host = controller.InnerRequest.RequestUri.Host,
						Port = controller.InnerRequest.RequestUri.Port
					}.Uri.ToString(), msg);

				}
			}
			msg.StatusCode = (HttpStatusCode)statusCode;
 
			msg.Headers.Add("WWW-Authenticate", string.Format("Bearer realm=\"Raven\", error=\"{0}\",error_description=\"{1}\"", error, errorDescription));

			return msg;
		}
예제 #9
0
        public bool TryAuthorize(RavenBaseApiController controller, bool hasApiKey, bool ignoreDbAccess, out HttpResponseMessage msg)
		{
			var isGetRequest = IsGetRequest(controller.InnerRequest.Method.Method, controller.InnerRequest.RequestUri.AbsolutePath);
			var allowUnauthenticatedUsers = // we need to auth even if we don't have to, for bundles that want the user 
				Settings.AnonymousUserAccessMode == AnonymousUserAccessMode.All ||
				Settings.AnonymousUserAccessMode == AnonymousUserAccessMode.Admin ||
					Settings.AnonymousUserAccessMode == AnonymousUserAccessMode.Get &&
					isGetRequest;

			var token = GetToken(controller);

			if (token == null)
			{
				if (allowUnauthenticatedUsers)
				{
					msg = controller.GetEmptyMessage();
					return true;
				}

				msg = WriteAuthorizationChallenge(controller, hasApiKey ? 412 : 401, "invalid_request", "The access token is required");

				return false;
			}

			AccessTokenBody tokenBody;
			if (!AccessToken.TryParseBody(Settings.OAuthTokenKey, token, out tokenBody))
			{
				if (allowUnauthenticatedUsers)
				{
					msg = controller.GetEmptyMessage();
					return true;
				}

				msg = WriteAuthorizationChallenge(controller, 401, "invalid_token", "The access token is invalid");

				return false;
			}

			if (tokenBody.IsExpired())
			{
				if (allowUnauthenticatedUsers)
				{
					msg = controller.GetEmptyMessage();
					return true;
				}

				msg = WriteAuthorizationChallenge(controller, 401, "invalid_token", "The access token is expired");

				return false;
			}

			var writeAccess = isGetRequest == false;
            if (!tokenBody.IsAuthorized(controller.TenantName, writeAccess))
			{
				if (allowUnauthenticatedUsers || ignoreDbAccess)
				{
					msg = controller.GetEmptyMessage();
					return true;
				}

				msg = WriteAuthorizationChallenge(controller, 403, "insufficient_scope",
					writeAccess ?
                    "Not authorized for read/write access for tenant " + controller.TenantName :
					"Not authorized for tenant " + controller.TenantName);

				return false;
			}

            controller.User = new OAuthPrincipal(tokenBody, controller.TenantName);
			CurrentOperationContext.Headers.Value[Constants.RavenAuthenticatedUser] = tokenBody.UserId;
			CurrentOperationContext.User.Value = controller.User;
			msg = controller.GetEmptyMessage();

			return true;
		}
예제 #10
0
        public bool TryAuthorize(RavenBaseApiController controller, bool ignoreDb, out HttpResponseMessage msg)
		{
			Func<HttpResponseMessage> onRejectingRequest;
			var tenantId = controller.TenantName ?? Constants.SystemDatabase;
			var userCreated = TryCreateUser(controller, tenantId, out onRejectingRequest);
			if (server.SystemConfiguration.AnonymousUserAccessMode == AnonymousUserAccessMode.None && userCreated == false)
			{
				msg = onRejectingRequest();
				return false;
			}

			PrincipalWithDatabaseAccess user = null;
			if (userCreated)
			{
				user = (PrincipalWithDatabaseAccess)controller.User;
				CurrentOperationContext.Headers.Value[Constants.RavenAuthenticatedUser] = controller.User.Identity.Name;
				CurrentOperationContext.User.Value = controller.User;

				// admins always go through
				if (user.Principal.IsAdministrator(server.SystemConfiguration.AnonymousUserAccessMode))
				{
					msg = controller.GetEmptyMessage();
					return true;
				}

				// backup operators can go through
				if (user.Principal.IsBackupOperator(server.SystemConfiguration.AnonymousUserAccessMode))
				{
					msg = controller.GetEmptyMessage();
					return true;
				}
			}

			bool isGetRequest = IsGetRequest(controller.InnerRequest.Method.Method, controller.InnerRequest.RequestUri.AbsolutePath);
			switch (server.SystemConfiguration.AnonymousUserAccessMode)
			{
				case AnonymousUserAccessMode.Admin:
				case AnonymousUserAccessMode.All:
					msg = controller.GetEmptyMessage();
					return true; // if we have, doesn't matter if we have / don't have the user
				case AnonymousUserAccessMode.Get:
					if (isGetRequest)
					{
						msg = controller.GetEmptyMessage();
						return true;
					}
					goto case AnonymousUserAccessMode.None;
				case AnonymousUserAccessMode.None:
					if (userCreated)
					{
						if (string.IsNullOrEmpty(tenantId) == false && tenantId.StartsWith("fs/"))
							tenantId = tenantId.Substring(3);

						if (string.IsNullOrEmpty(tenantId) == false && tenantId.StartsWith("counters/"))
							tenantId = tenantId.Substring(9);

					    if (user.AdminDatabases.Contains(tenantId) ||
					        user.AdminDatabases.Contains("*") || ignoreDb)
					    {
					        msg = controller.GetEmptyMessage();
					        return true;
					    }
					    if (user.ReadWriteDatabases.Contains(tenantId) ||
					        user.ReadWriteDatabases.Contains("*"))
					    {
					        msg = controller.GetEmptyMessage();
					        return true;
					    }
					    if (isGetRequest && (user.ReadOnlyDatabases.Contains(tenantId) ||
					                            user.ReadOnlyDatabases.Contains("*")))
					    {
					        msg = controller.GetEmptyMessage();
					        return true;
					    }
					}

					msg = onRejectingRequest();
					return false;
				default:
					throw new ArgumentOutOfRangeException();
			}
		}
예제 #11
0
        private static HttpResponseMessage ProvideDebugAuthInfo(RavenBaseApiController controller, object msg)
		{
			string debugAuth = controller.GetQueryStringValue("debug-auth");
			if (debugAuth == null)
				return controller.GetEmptyMessage();

			bool shouldProvideDebugAuthInformation;
			if (bool.TryParse(debugAuth, out shouldProvideDebugAuthInformation) && shouldProvideDebugAuthInformation)
			{
				return controller.GetMessageWithObject(msg);
			}

			return controller.GetEmptyMessage();
		}
예제 #12
0
        public bool TryAuthorize(RavenBaseApiController controller, bool hasApiKey, bool ignoreDbAccess, out HttpResponseMessage msg)
        {
            var isGetRequest = IsGetRequest(controller);
            var allowUnauthenticatedUsers = // we need to auth even if we don't have to, for bundles that want the user
                                            Settings.AnonymousUserAccessMode == AnonymousUserAccessMode.All ||
                                            Settings.AnonymousUserAccessMode == AnonymousUserAccessMode.Admin ||
                                            Settings.AnonymousUserAccessMode == AnonymousUserAccessMode.Get &&
                                            isGetRequest;

            var token = GetToken(controller);

            if (token == null)
            {
                if (allowUnauthenticatedUsers)
                {
                    msg = controller.GetEmptyMessage();
                    return(true);
                }

                msg = WriteAuthorizationChallenge(controller, hasApiKey ? 412 : 401, "invalid_request", "The access token is required");

                return(false);
            }

            AccessTokenBody tokenBody;

            if (!AccessToken.TryParseBody(Settings.OAuthTokenKey, token, out tokenBody))
            {
                if (allowUnauthenticatedUsers)
                {
                    msg = controller.GetEmptyMessage();
                    return(true);
                }

                msg = WriteAuthorizationChallenge(controller, 401, "invalid_token", "The access token is invalid");

                return(false);
            }

            if (tokenBody.IsExpired())
            {
                if (allowUnauthenticatedUsers)
                {
                    msg = controller.GetEmptyMessage();
                    return(true);
                }

                msg = WriteAuthorizationChallenge(controller, 401, "invalid_token", "The access token is expired");

                return(false);
            }

            var writeAccess = isGetRequest == false;

            if (!tokenBody.IsAuthorized(controller.ResourceName, writeAccess))
            {
                if (allowUnauthenticatedUsers || ignoreDbAccess)
                {
                    msg = controller.GetEmptyMessage();
                    return(true);
                }

                msg = WriteAuthorizationChallenge(controller, 403, "insufficient_scope",
                                                  writeAccess ?
                                                  "Not authorized for read/write access for tenant " + controller.ResourceName :
                                                  "Not authorized for tenant " + controller.ResourceName);

                return(false);
            }

            controller.User = new OAuthPrincipal(tokenBody, controller.ResourceName);
            CurrentOperationContext.User.Value = controller.User;
            msg = controller.GetEmptyMessage();

            return(true);
        }
예제 #13
0
        private bool TryAuthorizeSingleUseAuthToken(RavenBaseApiController controller, string token, out HttpResponseMessage msg)
		{
            if (controller.WasAlreadyAuthorizedUsingSingleAuthToken)
            {
                msg = controller.GetEmptyMessage();
                return true;
            }

            object result;
            HttpStatusCode statusCode;
            IPrincipal user;
            var success = TryAuthorizeSingleUseAuthToken(token, controller.TenantName, out result, out statusCode, out user);
            controller.User = user;
            if (success == false)
                msg = controller.GetMessageWithObject(result, statusCode);
            else
                msg = controller.GetEmptyMessage();

            controller.WasAlreadyAuthorizedUsingSingleAuthToken = success;
            return success;
        }
예제 #14
0
        public bool TryAuthorize(RavenBaseApiController controller, bool ignoreDb, out HttpResponseMessage msg)
        {
            Func <HttpResponseMessage> onRejectingRequest;
            var tenantId    = controller.TenantName ?? Constants.SystemDatabase;
            var userCreated = TryCreateUser(controller, tenantId, out onRejectingRequest);

            if (server.SystemConfiguration.AnonymousUserAccessMode == AnonymousUserAccessMode.None && userCreated == false)
            {
                msg = onRejectingRequest();
                return(false);
            }

            PrincipalWithDatabaseAccess user = null;

            if (userCreated)
            {
                user = (PrincipalWithDatabaseAccess)controller.User;
                CurrentOperationContext.Headers.Value[Constants.RavenAuthenticatedUser] = controller.User.Identity.Name;
                CurrentOperationContext.User.Value = controller.User;

                // admins always go through
                if (user.Principal.IsAdministrator(server.SystemConfiguration.AnonymousUserAccessMode))
                {
                    msg = controller.GetEmptyMessage();
                    return(true);
                }

                // backup operators can go through
                if (user.Principal.IsBackupOperator(server.SystemConfiguration.AnonymousUserAccessMode))
                {
                    msg = controller.GetEmptyMessage();
                    return(true);
                }
            }

            bool isGetRequest = IsGetRequest(controller.InnerRequest.Method.Method, controller.InnerRequest.RequestUri.AbsolutePath);

            switch (server.SystemConfiguration.AnonymousUserAccessMode)
            {
            case AnonymousUserAccessMode.Admin:
            case AnonymousUserAccessMode.All:
                msg = controller.GetEmptyMessage();
                return(true);                        // if we have, doesn't matter if we have / don't have the user

            case AnonymousUserAccessMode.Get:
                if (isGetRequest)
                {
                    msg = controller.GetEmptyMessage();
                    return(true);
                }
                goto case AnonymousUserAccessMode.None;

            case AnonymousUserAccessMode.None:
                if (userCreated)
                {
                    if (string.IsNullOrEmpty(tenantId) || tenantId.StartsWith("fs/") == false)
                    {
                        if (user.AdminDatabases.Contains(tenantId) ||
                            user.AdminDatabases.Contains("*") || ignoreDb)
                        {
                            msg = controller.GetEmptyMessage();
                            return(true);
                        }
                        if (user.ReadWriteDatabases.Contains(tenantId) ||
                            user.ReadWriteDatabases.Contains("*"))
                        {
                            msg = controller.GetEmptyMessage();
                            return(true);
                        }
                        if (isGetRequest && (user.ReadOnlyDatabases.Contains(tenantId) ||
                                             user.ReadOnlyDatabases.Contains("*")))
                        {
                            msg = controller.GetEmptyMessage();
                            return(true);
                        }
                    }
                    else if (tenantId.StartsWith("fs/"))
                    {
                        tenantId = tenantId.Substring(3, tenantId.Length - "fs/".Length);

                        if (user.ReadWriteFileSystems.Contains(tenantId) ||
                            user.ReadWriteFileSystems.Contains("*"))
                        {
                            msg = controller.GetEmptyMessage();
                            return(true);
                        }
                        if (isGetRequest && (user.ReadOnlyFileSystems.Contains(tenantId) ||
                                             user.ReadOnlyFileSystems.Contains("*")))
                        {
                            msg = controller.GetEmptyMessage();
                            return(true);
                        }
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException("tenantId", "We don't know how to authorize unknown tenant id: " + tenantId);
                    }
                }

                msg = onRejectingRequest();
                return(false);

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
예제 #15
0
        public bool TryAuthorize(RavenBaseApiController controller, bool ignoreDb, out HttpResponseMessage msg)
        {
            Func <HttpResponseMessage> onRejectingRequest;
            var tenantId    = controller.ResourceName ?? Constants.SystemDatabase;
            var userCreated = TryCreateUser(controller, tenantId, out onRejectingRequest);

            if (server.SystemConfiguration.Core.AnonymousUserAccessMode == AnonymousUserAccessMode.None && userCreated == false)
            {
                msg = onRejectingRequest();
                return(false);
            }

            PrincipalWithDatabaseAccess user = null;

            if (userCreated)
            {
                user = (PrincipalWithDatabaseAccess)controller.User;
                CurrentOperationContext.User.Value = controller.User;

                // admins always go through
                if (user.Principal.IsAdministrator(server.SystemConfiguration.Core.AnonymousUserAccessMode))
                {
                    msg = controller.GetEmptyMessage();
                    return(true);
                }

                // backup operators can go through
                if (user.Principal.IsBackupOperator(server.SystemConfiguration.Core.AnonymousUserAccessMode))
                {
                    msg = controller.GetEmptyMessage();
                    return(true);
                }
            }

            bool isGetRequest = IsGetRequest(controller);

            switch (server.SystemConfiguration.Core.AnonymousUserAccessMode)
            {
            case AnonymousUserAccessMode.Admin:
            case AnonymousUserAccessMode.All:
                msg = controller.GetEmptyMessage();
                return(true);    // if we have, doesn't matter if we have / don't have the user

            case AnonymousUserAccessMode.Get:
                if (isGetRequest)
                {
                    msg = controller.GetEmptyMessage();
                    return(true);
                }
                goto case AnonymousUserAccessMode.None;

            case AnonymousUserAccessMode.None:
                if (userCreated)
                {
                    if (string.IsNullOrEmpty(tenantId) == false &&
                        (tenantId.StartsWith("fs/", StringComparison.OrdinalIgnoreCase) ||
                         tenantId.StartsWith("cs/", StringComparison.OrdinalIgnoreCase) ||
                         tenantId.StartsWith("ts/", StringComparison.OrdinalIgnoreCase)))
                    {
                        tenantId = tenantId.Substring(3);
                    }

                    if (user.AdminDatabases.Contains(tenantId) ||
                        user.AdminDatabases.Contains("*") || ignoreDb)
                    {
                        msg = controller.GetEmptyMessage();
                        return(true);
                    }
                    if (user.ReadWriteDatabases.Contains(tenantId) ||
                        user.ReadWriteDatabases.Contains("*"))
                    {
                        msg = controller.GetEmptyMessage();
                        return(true);
                    }
                    if (isGetRequest && (user.ReadOnlyDatabases.Contains(tenantId) ||
                                         user.ReadOnlyDatabases.Contains("*")))
                    {
                        msg = controller.GetEmptyMessage();
                        return(true);
                    }
                }

                msg = onRejectingRequest();
                return(false);

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
예제 #16
0
        private bool TryAuthorizeSingleUseAuthToken(RavenBaseApiController controller, string token, out HttpResponseMessage msg)
		{
			OneTimeToken value;
			if (singleUseAuthTokens.TryRemove(token, out value) == false)
			{
				msg = controller.GetMessageWithObject(
					new
					{
						Error = "Unknown single use token, maybe it was already used?"
					}, HttpStatusCode.Forbidden);
				return false;
			}

			if (string.Equals(value.DatabaseName, controller.TenantName, StringComparison.InvariantCultureIgnoreCase) == false &&
                (value.DatabaseName == "<system>" && controller.TenantName == null) == false)
			{
				msg = controller.GetMessageWithObject(
					new
					{
						Error = "This single use token cannot be used for this database"
					}, HttpStatusCode.Forbidden);
				return false;
			}
			if ((SystemTime.UtcNow - value.GeneratedAt).TotalMinutes > 2.5)
			{
				msg = controller.GetMessageWithObject(
					new
					{
						Error = "This single use token has expired"
					}, HttpStatusCode.Forbidden);
				return false;
			}

			if (value.User != null)
			{
				CurrentOperationContext.Headers.Value[Constants.RavenAuthenticatedUser] = value.User.Identity.Name;
			}

			CurrentOperationContext.User.Value = value.User;
			controller.User = value.User;
			msg = controller.GetEmptyMessage();
			return true;
		}