2013-10-15 18:46:44 +11:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
2013-08-12 15:06:12 +02:00
|
|
|
|
using System.Net;
|
|
|
|
|
|
using System.Net.Http;
|
|
|
|
|
|
using System.Web;
|
2013-12-02 17:20:50 +11:00
|
|
|
|
using System.Web.Helpers;
|
2013-08-12 15:06:12 +02:00
|
|
|
|
using System.Web.Http;
|
2013-12-02 13:31:44 +11:00
|
|
|
|
using System.Web.Http.Controllers;
|
2013-11-20 14:18:03 +11:00
|
|
|
|
using System.Web.Security;
|
2013-08-26 11:28:15 +10:00
|
|
|
|
using AutoMapper;
|
2013-10-15 18:46:44 +11:00
|
|
|
|
using Umbraco.Core;
|
2013-11-20 14:18:03 +11:00
|
|
|
|
using Umbraco.Core.Configuration;
|
|
|
|
|
|
using Umbraco.Core.Models.Membership;
|
2013-08-12 15:06:12 +02:00
|
|
|
|
using Umbraco.Web.Models.ContentEditing;
|
|
|
|
|
|
using Umbraco.Web.Models.Mapping;
|
|
|
|
|
|
using Umbraco.Web.Mvc;
|
2013-10-15 18:46:44 +11:00
|
|
|
|
using Umbraco.Core.Security;
|
2013-08-12 15:06:12 +02:00
|
|
|
|
using Umbraco.Web.Security;
|
|
|
|
|
|
using Umbraco.Web.WebApi;
|
|
|
|
|
|
using Umbraco.Web.WebApi.Filters;
|
2013-11-20 14:18:03 +11:00
|
|
|
|
using umbraco.providers;
|
2013-08-12 15:06:12 +02:00
|
|
|
|
|
|
|
|
|
|
namespace Umbraco.Web.Editors
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// The API controller used for editing content
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[PluginController("UmbracoApi")]
|
|
|
|
|
|
[ValidationFilter]
|
2013-12-06 15:01:58 +11:00
|
|
|
|
[AngularJsonOnlyConfiguration]
|
2013-08-12 15:06:12 +02:00
|
|
|
|
public class AuthenticationController : UmbracoApiController
|
|
|
|
|
|
{
|
2013-10-15 18:46:44 +11:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// This is a special method that will return the current users' remaining session seconds, the reason
|
|
|
|
|
|
/// it is special is because this route is ignored in the UmbracoModule so that the auth ticket doesn't get
|
|
|
|
|
|
/// updated with a new timeout.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
[WebApi.UmbracoAuthorize]
|
2013-12-03 11:36:17 +11:00
|
|
|
|
[ValidateAngularAntiForgeryToken]
|
2013-10-15 18:46:44 +11:00
|
|
|
|
public double GetRemainingTimeoutSeconds()
|
|
|
|
|
|
{
|
|
|
|
|
|
var httpContextAttempt = TryGetHttpContext();
|
|
|
|
|
|
if (httpContextAttempt.Success)
|
|
|
|
|
|
{
|
|
|
|
|
|
return httpContextAttempt.Result.GetRemainingAuthSeconds();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//we need an http context
|
|
|
|
|
|
throw new NotSupportedException("An HttpContext is required for this request");
|
|
|
|
|
|
}
|
2013-08-12 15:06:12 +02:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2013-10-01 13:23:13 +10:00
|
|
|
|
/// Checks if the current user's cookie is valid and if so returns OK or a 400 (BadRequest)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
[HttpGet]
|
|
|
|
|
|
public HttpResponseMessage IsAuthenticated()
|
|
|
|
|
|
{
|
|
|
|
|
|
var attempt = UmbracoContext.Security.AuthorizeRequest();
|
|
|
|
|
|
if (attempt == ValidateRequestAttempt.Success)
|
|
|
|
|
|
{
|
|
|
|
|
|
return Request.CreateResponse(HttpStatusCode.OK);
|
|
|
|
|
|
}
|
2013-10-02 09:53:58 +10:00
|
|
|
|
//return BadRequest (400), we don't want to return a 401 because that get's intercepted
|
2013-10-01 13:23:13 +10:00
|
|
|
|
// by our angular helper because it thinks that we need to re-perform the request once we are
|
2013-10-02 09:53:58 +10:00
|
|
|
|
// authorized and we don't want to return a 403 because angular will show a warning msg indicating
|
|
|
|
|
|
// that the user doesn't have access to perform this function, we just want to return a normal invalid msg.
|
|
|
|
|
|
return Request.CreateResponse(HttpStatusCode.BadRequest);
|
2013-10-01 13:23:13 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2013-10-15 18:46:44 +11:00
|
|
|
|
/// Returns the currently logged in Umbraco user
|
2013-08-12 15:06:12 +02:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
2013-12-03 11:57:41 +11:00
|
|
|
|
/// <remarks>
|
|
|
|
|
|
/// We have the attribute [SetAngularAntiForgeryTokens] applied because this method is called initially to determine if the user
|
|
|
|
|
|
/// is valid before the login screen is displayed. The Auth cookie can be persisted for up to a day but the csrf cookies are only session
|
|
|
|
|
|
/// cookies which means that the auth cookie could be valid but the csrf cookies are no longer there, in that case we need to re-set the csrf cookies.
|
|
|
|
|
|
/// </remarks>
|
2013-10-15 18:46:44 +11:00
|
|
|
|
[WebApi.UmbracoAuthorize]
|
2013-12-03 11:57:41 +11:00
|
|
|
|
[SetAngularAntiForgeryTokens]
|
2013-08-12 15:06:12 +02:00
|
|
|
|
public UserDetail GetCurrentUser()
|
|
|
|
|
|
{
|
2013-10-15 18:46:44 +11:00
|
|
|
|
var user = Services.UserService.GetUserById(UmbracoContext.Security.GetUserId());
|
|
|
|
|
|
var result = Mapper.Map<UserDetail>(user);
|
|
|
|
|
|
var httpContextAttempt = TryGetHttpContext();
|
|
|
|
|
|
if (httpContextAttempt.Success)
|
2013-08-12 15:06:12 +02:00
|
|
|
|
{
|
2013-10-15 18:46:44 +11:00
|
|
|
|
//set their remaining seconds
|
|
|
|
|
|
result.SecondsUntilTimeout = httpContextAttempt.Result.GetRemainingAuthSeconds();
|
2013-08-12 15:06:12 +02:00
|
|
|
|
}
|
2013-10-15 18:46:44 +11:00
|
|
|
|
return result;
|
2013-08-12 15:06:12 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Logs a user in
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="username"></param>
|
|
|
|
|
|
/// <param name="password"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2013-12-03 11:36:17 +11:00
|
|
|
|
[SetAngularAntiForgeryTokens]
|
2013-08-12 15:06:12 +02:00
|
|
|
|
public UserDetail PostLogin(string username, string password)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (UmbracoContext.Security.ValidateBackOfficeCredentials(username, password))
|
|
|
|
|
|
{
|
2013-11-20 14:18:03 +11:00
|
|
|
|
var user = Security.GetBackOfficeUser(username);
|
|
|
|
|
|
|
2013-08-12 15:06:12 +02:00
|
|
|
|
//TODO: Clean up the int cast!
|
2013-12-03 11:36:17 +11:00
|
|
|
|
var ticket = UmbracoContext.Security.PerformLogin(user);
|
|
|
|
|
|
|
|
|
|
|
|
var http = this.TryGetHttpContext();
|
|
|
|
|
|
if (http.Success == false)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new InvalidOperationException("This method requires that an HttpContext be active");
|
|
|
|
|
|
}
|
|
|
|
|
|
http.Result.AuthenticateCurrentRequest(ticket, false);
|
|
|
|
|
|
|
2013-10-15 18:46:44 +11:00
|
|
|
|
var result = Mapper.Map<UserDetail>(user);
|
2013-10-16 12:00:42 +11:00
|
|
|
|
//set their remaining seconds
|
2013-12-03 11:36:17 +11:00
|
|
|
|
result.SecondsUntilTimeout = ticket.GetRemainingAuthSeconds();
|
2013-10-15 18:46:44 +11:00
|
|
|
|
return result;
|
2013-08-12 15:06:12 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2013-10-02 13:42:36 +10:00
|
|
|
|
//return BadRequest (400), we don't want to return a 401 because that get's intercepted
|
2013-08-12 15:06:12 +02:00
|
|
|
|
// by our angular helper because it thinks that we need to re-perform the request once we are
|
2013-10-02 13:42:36 +10:00
|
|
|
|
// authorized and we don't want to return a 403 because angular will show a warning msg indicating
|
|
|
|
|
|
// that the user doesn't have access to perform this function, we just want to return a normal invalid msg.
|
|
|
|
|
|
throw new HttpResponseException(HttpStatusCode.BadRequest);
|
2013-08-12 15:06:12 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2013-11-20 14:18:03 +11:00
|
|
|
|
|
2013-08-12 15:06:12 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Logs the current user out
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
2013-12-02 17:20:50 +11:00
|
|
|
|
[UmbracoBackOfficeLogout]
|
|
|
|
|
|
[ClearAngularAntiForgeryToken]
|
2013-12-03 11:36:17 +11:00
|
|
|
|
[ValidateAngularAntiForgeryToken]
|
2013-08-12 15:06:12 +02:00
|
|
|
|
public HttpResponseMessage PostLogout()
|
2013-12-02 17:20:50 +11:00
|
|
|
|
{
|
2013-08-12 15:06:12 +02:00
|
|
|
|
return Request.CreateResponse(HttpStatusCode.OK);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2013-06-17 01:06:31 +02:00
|
|
|
|
}
|