.net core 2.0
I have a HomeController with Views, ect. From a same/different controller that has issued a GET to another web site, I need to "start/redirect" to my HomeController. Maybe a bit hard to explain but I'm trying to simulate an Oauth flow where I need to check to see if a user is logged on and if not redirect the user's browser to my signon page. Seems like it ought to be simple out I'm not having any luck. So if I have the code below, can I start up a new browser session with my logon page:
public IActionResult Logon()
{
return View();
}
HttpGet("auth")]
public void Get(string client_id, string redirect_uri, string state, string scope, string response_type)
{
if(!isloggedOn)
{
LocalRedirectPermanent("Logon");
}
}
Turns out Postman will not redirect to a http URL. You have to be able to get the redirect on https. Buried not too deep in the documentation.
Related
I have a super simple Authentication Attribute that I'm trying to implement in an ASP.NET MVC 5 application and I'm having some trouble. I want the attribute to be applied globally, except for specific actions within a controller (for example the login form and the home page).
I've tried decorating the action with the [OverrideAuthentication] attribute with no luck. It gives me a redirect loop error because the application is still running the authentication on the login form, and keeps trying to redirect back to the login form over and over.
Has anyone else seen this behaviour? Any idea what I've stuffed up here?
By way of example, I've created a super simple filter that is currently unimplemented:
public class BasicAuthenticationAttribute
: ActionFilterAttribute, IAuthenticationFilter
{
public void OnAuthentication(AuthenticationContext filterContext)
{
throw new NotImplementedException();
}
public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
{
throw new NotImplementedException();
}
}
If I decorate my controller/action like this:
[BasicAuthentication]
public class AccountController : Controller
{
[HttpGet]
[OverrideAuthentication]
public ActionResult Login()
{
return View();
}
}
I get a not implemented exception when I navigate to the Login action, even though that action shouldn't be running the authentication code at all. Have I misunderstood how overrides are supposed to work?
I think you have confused authentication with authorization (as many people do). It doesn't make sense to make a [BasicAuthenticationAttribute] and register it globally, because authentication only happens upon login, not on every request.
Authorization is what takes place after the user has logged in to check whether the user has the required privileges to do a specific action, and it makes sense to do authorization globally. Authorization in MVC is handled by the [AuthorizeAttribute] and you can inherit it if you need to customize the way the authorization check is done. You can also register it as a global filter.
The [AllowAnonymousAttribute] works in conjunction with [AuthorizeAttribute], and basically tells it to skip the authorization check. It should also be noted that the [AllowAnonymousAttribute] will have no effect unless it is used with the [AuthorizeAttribute].
I currently have an ASP.NET MVC 4 website where members have an account and can log in using both Facebook and my own login form. I am then using FormsAuthentication.
I would next like to build an API, using WebAPI and expose some of my functionality to a mobile client I am planning on building.
I do not have any plans on having others consume my API, so this would just be for the client I build.
How would I go about implementing security on the WebAPI? Should I be using a token system where I can have a login form on the client, receive the credentials, log them in, and return a token which would be send back to the server on each call?
Should I implement oAuth on the server?
Try to be completely RESTful: use HTTP's built-in authentication system where authentication information is provided by the client in each request. You can also use HTTP Basic Authentication without any security concerns provided that you use SSL, otherwise HTTP Digest is also secure enough for this purpose.
You will need to implement your own HTTP Basic Authentication provider for ASP.NET, fortunately it's easy (and fun!).
It also beats other systems which require a signed URI using a querystring parameter, which is ugly and messes up lovely REStfulness, or carrying a token around (usually passed as a cookie).
Holy wars about how to do authentication in rest aside, you can just use forms authentication. If you are also using a web interface from the same site/domain and you have your authentication stuff well factored this is really convenient and easy.
you need a base class for your api controllers
public class MyApiControllerBase : ApiController
{
public MySecurityContextType SecurityContext { get; set; }
}
an ActionFilterAttribute
public class AuthenticationContextAttribute : System.Web.Http.Filters.ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
MyApiControllerBase controller = actionContext.ControllerContext.Controller as MyApiControllerBase ;
if (controller != null)
{
var context = ((HttpContextBase)controller.Request.Properties["MS_HttpContext"]);
HttpCookie cookie = context.Request.Cookies[FormsAuthentication.FormsCookieName];
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
controller.SecurityContext= ParseFormsAuthenticationTicket(ticket);
}
}
}
and code to create the ticket in the first place.
LogIn(HttpRequestBase httpRequest, string userName, string password)
{
var context = DoLoginLogic(userName,password);
FormsAuthentication.SetAuthCookie(context, usePersistentCookies);
}
Authorization will obviously need to be done in the controller methods.
I would like to set up a system that use both technologies at the same time. My MVC application generates and returns html/css/jaavascript files and then I do some work on the client side that get data through ajax request. Nothing new so far, but I would like also that the ajax endpoing could also be use as a pure REST service .
How can I have a uniform way to authentificate (web forms for MVC clients(that will then use the REST enpoints for the ajax requests) , something else for pure REST clients ).
Thanks
You could use the [Authorize] attribute (the System.Web.Http.AuthorizeAttribute one and not System.Web.Mvc.AuthorizeAttribute) on your Web API controller actions:
public class ValuesController: ApiController
{
[Authorize]
public HttpResponseMessage Get()
{
string username = User.Identity.Name;
...
}
}
I have one View called SignIn that contains two partial views for authentication. One is for OpenID and the other is for logging in to my site using an internal account.
The Action for the OpenID form goes to an OpenIDSignIn() Action while the other just points to SignIn(). Everything works great except for when a user clicks a link to a view that requires them to be logged on [Authorize] etc..
I see the returnUrl in the QueryString however this value is not available to the current controller action, due to the fact that they will be either be logging in with OpenID or normally, thus caling the ActionResult associated with either of those views.
Just for clarification the returnUrl is the one that gets thrown in there from FormsAuthentication and is used when doing a RedirectFromLoginPage etc..
public ActionResult SignIn(string returnUrl)
{
if(!string.IsNullOrEmpty(returnUrl))
{
if(UrlUtil.IsLocalUrl(returnUrl))
{
Session.Add("ReturnUrl", returnUrl);
}
else
{
return RedirectToAction("SignIn", "Account");
}
}
return View();
}
This seems to be a viable workaround. However I hate session variables!
This seems like a pretty stupid question, but I'm trying to figure out the best way to do this. Would you simply redirect to a /Logout page and have the controller call the FormsAuthentication.SignOut function?
That was my first thought, but then I wondered if it could be abused by third party websites. Let's say someone just decides to post a link to your /Logout page. The user would get signed out of your application. Is there a good way to prevent that?
If you are concerned about a user getting accidentally logged out of you application through the use of a malicious link, you can check the Referrer to make sure that the logout is coming from your site (or is NULL in the case where the user simply types the URL in).
I actually don't worry about this since logging someone out is annoying but not necessarily a security risk.
Such a malicious link would be an example of a class of security vulnerabilities known as cross site request forgery, CSRF. A logout link is relatively harmless, but a remote site could set up a number of hidden forms and post them to your site to perform any action possible through POST.
The most common counter-measure is to include a challenge, a random hidden value in each form, and then check for that value. Checking the referer header could work, but note that some browsers don't send referer at all.
Read more: http://en.wikipedia.org/wiki/Cross-site_request_forgery
This is an old question, but here is a modern example with MVC:
[Authorize]
public RedirectResult Logout()
{
FormsAuthentication.SignOut();
return this.Redirect("/");
}
You can ensure that the Logout action is only able to be called by somebody who is logged in by applying the Authorize attribute to it.
This is what I use.
public ActionResult Logout()
{
FormsAuthentication.SignOut();
return RedirectToAction("Index", "Home");
}
Seems to work fine.
Third party websites are only going to log themselves out. So they wouldn't be achieving anything different from actually clicking Logout.
The new ASP.net MVC Beta contains an AccountController, which may be worth looking at, as it essentially implements everything from Registration to Login/Logout to Forgot Password functionality. Not sure how good it is, but a good starting Point for sure.
Derive from ActionResult
public class LogoutResult : ActionResult
{
private readonly IAuthenticationService _authenticationService;
private readonly IWebContext _context;
public LogoutResult(IAuthenticationService authenticationService, IWebContext context)
{
_authenticationService = authenticationService;
_context = context;
}
public override void ExecuteResult(ControllerContext context)
{
_authenticationService.Logout();
_context.Abandon();
_context.Redirect("~/");
}
}
You should look for a cookie or something that identifies the client as the true user.