ASP.NET Core 3.1 Razor Pages: How to automatically redirect to Login page from Index page? - razor-pages

I am building a web application using the ASP.NET Core 3.1 MVC and Razor pages.
I am new to Razor pages.
I created a basic application using above. I want to load the Login page on start of the application but
the Index.cshtml page seems to be the start page.
To redirect from the Index.cshtml page (start page) to my Login.cshtml page, I did following in the Index.cshtml PageModel. But it is not working.
EDITED:
Index.cshtml:
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about building Web apps with ASP.NET Core.</p>
<form method="get" asp-page="Index" hidden name="myForm">
<input type="submit" name="submit" value="Redirect 1" asp-page-handler="Redirect1" hidden />
</form>
</div>
Index.cshtml.cs:
public class IndexModel : PageModel
{
public IndexModel()
{
OnPostRedirect1();
}
public void OnGet() {}
public IActionResult OnPostRedirect1()
{
return RedirectToPage("Login");
}
}
How to automatically redirect to Login page from Index page?

You have some options. If you don't want unauthorised users to visit the Index page, apply the [Authorize] attribute to the PageModel class:
[Authorize]
public class IndexModel : PageModel
{
...
}
Then, if your login page is not located at /account/login, configure the login page in Startup:
services.ConfigureApplicationCookie(options =>
{
options.LoginPath = "/YourLoginPage";
});
The framework will automatically redirect unauthenticated users to the login page. This is what most people are likely to do. Or, if you don't want Index at all, remove it and set the login page as the home page by changing its route template:
#page "/"
This will override the conventional route for the page, based on its file path: https://www.learnrazorpages.com/razor-pages/routing#override-routes

Related

Integrate liferay 7.4 recaptcha with MVC Portlet and apache wicket

I have an old application uses wicket 1.4 and want to integrate the liferay reCAPTCHA ( liferay 7.4).
Is there any guide for that?
Or anyone might help ?
It worked for MVC portlet like the following but still cannot achieve same in wicket :
Use CAPTCHA or reCAPTCHA with custom portlet in Liferay MVC Portlet:
CAPTCHA is a “Completely Automated Public Turing test to tell Computers and Humans Apart”. It is used in the computer world to determine whether an end-user is human or non-human. Liferay provides the necessary API as well as tag library to implement CAPTCHA in your custom portlet. Also, you can integrate Google reCAPTCHA in your custom portlet.
Prerequisites
Java
Liferay portal 7/7.x
Use CAPTCHA in custom portlet
Assuming you’ve already created a Liferay-workspace project
Follow below steps to implement CAPTCHA in your custom portlet
Create MVC Portlet
Go to liferay workspace project → modules → new
Select other → Liferay → Liferay Module Project and Click on Next
Enter project name
Select “Project Template Name” as “mvc-portlet” and Click on “Next”
Enter Package name and Click on “Finish”
The necessary file structure for MVC module will get created as below :
2) Now we add below code in view.jsp
<%# include file="/init.jsp" %>
<%# taglib uri="http://liferay.com/tld/util" prefix="liferay-util" %>
<%# taglib uri="http://liferay.com/tld/captcha" prefix="liferay-captcha" %>
<%# page import="com.liferay.portal.kernel.captcha.CaptchaTextException"%>
<portlet:actionURL name="basicFormDataWithCaptcha" var="basicFormDataWithCaptchaAActionURL" />
<portlet:resourceURL id="captcha" var="captchaResourceURL"/>
<liferay-ui:error exception="<%= CaptchaTextException.class %>" message="captcha-verification-failed" />
<aui:form method="post" name="basicForm" action="<%= basicFormDataWithCaptchaAActionURL %>">
<aui:input name="firstName" >
<aui:validator name="alpha"/>
</aui:input>
<aui:input name="lastName" >
<aui:validator name="alpha"/>
</aui:input>
<liferay-captcha:captcha url="<%= captchaResourceURL %>"/>
<aui:button type="submit" value="Submit"></aui:button>
</aui:form>
3) Create Action method in CustomCaptchaPortlet
package ...;
import ...;
#Component(
...
)
public class CustomCaptchaPortlet extends MVCPortlet {
private Log log = LogFactoryUtil.getLog(this.getClass().getName());
#ProcessAction(name = "basicFormDataWithCaptcha")
public void basicFormDataWithCaptcha(ActionRequest actionRequest, ActionResponse actionResponse)
throws IOException, PortletException {
String firstName = ParamUtil.getString(actionRequest,"firstName");
String lastName=ParamUtil.getString(actionRequest,"lastName");
log.info("First Name : " + firstName);
log.info("Last Name : " + lastName);
try{
CaptchaUtil.check(actionRequest);
log.info("CAPTCHA verification successful.");
}catch(Exception exception) {
if(exception instanceof CaptchaTextException) {
SessionErrors.add(actionRequest, exception.getClass(), exception);
log.error("CAPTCHA verification failed.");
}
}
}
#Override
public void serveResource(ResourceRequest resourceRequest, ResourceResponse resourceResponse)
throws IOException, PortletException {
try {
CaptchaUtil.serveImage(resourceRequest, resourceResponse);
}catch(Exception exception) {
log.error(exception.getMessage(), exception);
}
}
protected boolean isCheckMethodOnProcessAction() {
return _CHECK_METHOD_ON_PROCESS_ACTION;
}
private static final boolean _CHECK_METHOD_ON_PROCESS_ACTION = false;}
Output with CAPTCHA
Use Google reCAPTCHA in custom portlet
To integrate Google reCAPTCHA in Liferay please follow below steps
1) Get Site key & Secret key from Google reCAPTCHA
Go to www.google.com/recaptcha in your web browser
Click on “Admin console” button (Located at top-right corner)
Fill up your details in the form and then click on “Submit”
4- You will get “Site key & Secret key” as below image. This you will require while configuring Google reCAPTCHA with Liferay
2) Enable Google reCAPTCHA in your Liferay
Login as admin user
Navigate to Control Panel → System Setting → SECURITY → Security Tools → CAPTCHA
Go to CAPTCHA Engine and change it to reCAPTCHA
Enter “reCAPTCHA public key” and “reCAPTCHA private key”
You need to enter the values you got from Google reCAPTCHA site in previse step , “reCAPTCHA public key” field, and “secret key” in “reCAPTCHA private key” field
Click on ‘Save’
To test Google reCAPTCHA is properly configured or not. Logout from Liferay and go to Create Account page. You can see a default Liferay CAPTCHA is replaced with the new Google reCAPTCHA
3) Use Google reCAPTCHA in your Custom Portlet
Once you configure reCAPTCHA from control panel below, code will render google reCAPTCHA
<liferay-captcha:captcha url="<%= captchaResourceURL %>"/>
If we configure reCAPTCHA from Liferay control panel, Output of above ‘custom-captcha-portlet’ will look like below
As you see it works for MVC portlet but I have some code written in apache wicket which I did not find a way to achieve same and wondering if there is a way to integrate Liferay reCAPTCHA with wicket somehow ?

Blazor using Azure AD authentication allowing anonymous access

I'm currently writing a (Server side) Blazor application that includes the default AzureAD Authentication.
This works well for authenticated users - challenging on the entrance (_Host.cshtml) file, redirecting and then back once authenticated.
I need to have a couple of pages not requiring authentication - I don't want the user being challenged and redirected to Microsoft.
What is the correct way to do this? I have experimented with the AllowAnonymousAttribute, the AllowAnonymousToPage razor pages options, nothing seems to stop the challenge.
Any help would be greatly appreciated!
Below is my setup for Authentication (ConfigureServices):
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => Configuration.Bind("AzureAd", options));
services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddTelerikBlazor();
}
And then the appropriate part in Configure:
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
I found what I had to do was add the following to _Hosts.cshtml
#using Microsoft.AspNetCore.Authorization
#attribute [AllowAnonymous]
Once I did this authorization was no longer required on any of the pages by default and I could then add it to the pages where I wanted to require it.
For example if you wanted to secure the Counter.razor page just add an Authorize attribute to the top:
#attribute [Authorize]
So now if you tried to access the counter page you will get a Not authorized message.
If you want to remove the counter link when the user is not logged in modify the NavMenu.razor and surround the Counter link with an <AuthorizeView> </AuthorizeView> as so:
<AuthorizeView>
<li class="nav-item px-3">
<NavLink class="nav-link" href="counter">
<span class="oi oi-plus" aria-hidden="true"></span> Counter
</NavLink>
</li>
</AuthorizeView>
Ideally I would have liked to just opt out of authorization for the index page and have everything else secured by default but I could not find a way to get that to work. If I tried adding the #attribute [AllowAnonymous] to the Index.razor page it seemed to ignore it.

simple jsf commandbutton work on every single page except home page

A Java EE 8/SE 8 web application in deployement runnnig on Glassfish 5 build 25 both production and development, uses jsf 2.3. users create accounts and login. there is a 'logout' button for loging out.
Problem: 'logout' button works as expected everywhere on the website. EXCEPT home page (example.com) & (example.com/home.xhtml). the problem does not exists on my local computer. only in production (example.com).
So I have a template called : index.xhtml . all pages use it, including home.xhtml:
<ui:composition template="index.xhtml">
<ui:define name="top-bar">
<c:if test="#{request.remoteUser ne null}">
<h:form ><h:commandButton value="Log out" action="#{registerAdvanced.logout}"/></h:form>
</c:if>
</ui:define>
and
#Named
#RequestScoped
public class RegisterAdvanced extends BaseBacking implements Serializable {
public String logout() {
try {
getRequest().logout();
getContext().getExternalContext().getSessionMap().remove("user");
return REDIRECT_PAGE;
} catch (ServletException ex) {
return REDIRECT_PAGE;
}
}
}
Users login & logout fairly easily until I noticied that clicking on logout on the home page (home.xhtml) prints a null pointer exception AND redirect to 404 error page.
[[/home.xhtml #450,77 value="#{passesTestBean.displayPassSummaryList}": java.lang.NullPointerException
javax.el.ELException: /home.xhtml #450,77 value="#{passesTestBean.displayPassSummaryList}": java.lang.NullPointerException
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:119)
at com.sun.faces.facelets.component.UIRepeat.getValue(UIRepeat.java:314)
at com.sun.faces.facelets.component.UIRepeat.getDataModel(UIRepeat.java:256)
at com.sun.faces.facelets.component.UIRepeat.setIndex(UIRepeat.java:507)
at com.sun.faces.facelets.component.UIRepeat.process(UIRepeat.java:557)
at com.sun.faces.facelets.component.UIRepeat.processDecodes(UIRepeat.java:861)
at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1258)....
part of jsf where there is a call to value="#{passesTestBean.displayPassSummaryList}" is 100% seperate to logout and PassesTestBean CDI is request scope.
so the problem is SOMEHOW when I click on logout button. PassesTestBean is called for no reason and not since jsf must Initialize (since Request Scoped). it ends up returning null.
Now remember this only happens in: production at example.com AND only home page of all pages.
I'm thinking of writing a page only for loging out: has a log out button only.
Check for null pointer exception
getRequest().logout(); //here
getContext().getExternalContext().getSessionMap().remove("user");//here

Anti-forgery validation fails when using Azure AD auth

We are implementing Html.AntiForgeryToken() in our AAD authenticated application. The login is working fine but when we click a button on home page it needs to call a controller action. It is failing to call controller action with below exception. Any idea to resolve this issue?
Error:
[HttpAntiForgeryException (0x80004005): The provided anti-forgery token was meant for user "xyz#microsoft.com", but the current user is "".]
html:
using (Html.BeginForm("ExternalLogin", "Account", new { ReturnUrl = Model.ReturnUrl })) {
#Html.AntiForgeryToken()
<div id="LoginList">
<p>
#foreach (AuthenticationDescription p in loginProviders) {
<md-button type="submit" class="btn facebook-theme-background" id="#p.AuthenticationType" name="provider" value="#p.AuthenticationType" title="Log in using your #p.Caption account">Login with #p.AuthenticationType</md-button>
}
</p>
</div>
}
Server Side: It is not even entering this method. When I comment ValidateAntiForgeryToken then it is entering.
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLogin(string provider, string returnUrl)
{
}
Using below two properties for authentication:
<add key="Tenant" value="xyz.onmicrosoft.com" />
<add key="Audience" value="<guid>" />
I am trying to reproduce this issue, however failed. It seems that the issue is relative to the code. You can refer the code sample which works well for me from this link.
If you still have the problem, you may share a run-able demo to help reproducing this issue.

Anonymous page - Intranet SharePoint 2013

I would like to create an anonymous page in SharePoint Intranet Site. All rest of the site is using windows claims authentication but I want to create single page which should be anonymous.
I believe there is a way to create a page in IIS under layouts directory and it can be accessible anonymously but I am not able to make it work. Anybody has any idea?
Editing it with the code I have so far
<%# Import Namespace="Microsoft.SharePoint" %>
<%# Page Language="C#" AutoEventWireup="true" Inherits="Microsoft.SharePoint.WebControls.UnsecuredLayoutsPageBase" DynamicMasterPageFile="~/_layouts/15/ErrorV15.master" %>
<HTML>
<script runat="server" language="C#">
protected override bool AllowAnonymousAccess
{ get{ return true; } }
protected override bool AllowNullWeb
{ get { return true; } }
protected void Page_Load(object sender, EventArgs e)
{
}
</script>
<body>
<form id="MyForm" runat="server">
Application page
</form>
</body>
</HTML>
Thanks!
In SharePoint, you shouldn't change any files manually.
You should start with a SharePoint form solution project in your Visual Studio and it will produce a WSP file. By installing it, the SharePoint platform will place it in the correct location (psst, the 15 hive).
In that project, you'll need to add an application page and it needs to inherit from UnsecuredLayoutsPageBase and override the AllowAnonymousAccess property, returning true.

Resources