How to dynamically authorize users in MVC inside Application_Start - asp.net-mvc-5

I am using MVC 5 to build an application. In my web.config I have defined a custom section which I will use to display menu to user. It is something like:
<Menus>
<Menu>
<MainMenu Title="Home"></MainMenu>
<SubMenus>
<SubMenu Title="Page1" PageName="home/index" ADGroup="BusinessUsers">
<SubMenu Title="Page2" PageName="home/index2" ADGroup="ITUsers">
</SubMenus>
</Menu>
<Menu>
<MainMenu Title="About Us"></MainMenu>
<SubMenus>
<SubMenu Title="Another Page1" PageName="about/mypage1" ADGroup="BusinessUsers">
<SubMenu Title="Some Other Page" PageName="about/mypage2" ADGroup="OtherUsers">
</SubMenus>
</Menu>
</Menus>
I am using Windows authentication and everyone will have access via AD groups. By default I have denied access to all users using authorization rule in web.config like below:
<authorization><deny users="*"/></authorization>
Is it possible to define authorization rules based on MENU above in Application_Start at runtime? Something like:
Global.Filters.AuthorizeUser("BusinessUsers", "home/index, about/mypage1");
Global.Filters.AuthorizeUser("ITUsers", "home/index2");

What you're doing here isn't a standard way of defining a menu, so there is no standard way of enforcing authorization on it. You will need to implement it yourself.
Somewhere in your code during a request, you will have to loop through each SubMenu and use HttpContext.Current.User.IsInRole("DOMAIN\\GroupName") to test whether the user is in the appropriate group. I can't give you any further direction than that without seeing more of your code.
I'm sure you have your reasons for putting this in web.config, but what I have done in my own projects is define the menu in a partial view and check the roles right in the view:
#if (HttpContext.Current.User.IsInRole("DOMAIN\\GroupName") {
Some menu item
}
If you're worried about being able to update the menu items without recompiling the whole project, then that's still fine since the cshtml files aren't compiled anyway - you can update it on the fly.

Related

Is it possible to load a Liferay portlet dynamically on a page from a .jsp file?

I have a portlet that is deployed on a page and I need to produce a link that will load a different portlet (which is in a different module) in full-screen mode. I can load the built in Login portlet this way without a problem, but when I try to load any of my custom portlets I get two red error boxes with the message "You do not have the roles required to access this portlet." And I have the permissions - I can access the portlet fine when added to a page - and I'm even testing with an omni-admin account.
The portlet ID that has the .jsp file is 'subscriptionmanagement_WAR_subscriptionmanagementportlet' and the portlet ID I'm trying to load is 'GRPSignupForm_WAR_NY511RMportlet'. The tag is:
<liferay-portlet:renderURL portletName="GRPSignupForm_WAR_NY511RMportlet" var="grpPortlet" windowState="<%= WindowState.MAXIMIZED.toString() %>">
</liferay-portlet:renderURL>
Which produces the URL: http://localhost:8080/group/test/unsubscribe?p_p_id=tripitinerary_WAR_NY511RMportlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view
However, as I've mentioned, I have been able to load other portlets in this way. The login portlet for example using the same tag works fine:
<liferay-portlet:renderURL portletName="<%= PortletKeys.LOGIN %>" var="loginURL" windowState="<%= WindowState.MAXIMIZED.toString() %>">
<portlet:param name="mvcRenderCommandName" value="/login/login" />
</liferay-portlet:renderURL>
The obvious difference is that it is passing a specific render command parameter, but otherwise it is the same. It produces the URL:
http://localhost:8080/group/test-1/unsubscribe?p_p_id=com_liferay_login_web_portlet_LoginPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&_com_liferay_login_web_portlet_LoginPortlet_mvcRenderCommandName=%2Flogin%2Flogin
For completeness, here is the code for the portlet I'm trying to load. But as I mentioned above, I have tried to load various portlets in this project and all of them produce the permissions error.
#Component(
immediate = true,
property = {
"com.liferay.portlet.display-category=root//NYSDOT//GRP",
"com.liferay.portlet.instanceable=false",
"com.liferay.portlet.header-portlet-css=/css/main.css",
"com.liferay.portlet.footer-portlet-javascript=/js/main.js",
"com.liferay.portlet.css-class-wrapper=grh-signup-form-portlet",
"javax.portlet.display-name=GRP Signup Form",
"javax.portlet.init-param.template-path=/html/",
"javax.portlet.init-param.add-process-action-success-action=false",
"javax.portlet.init-param.config-template=/html/configuration.jsp",
"javax.portlet.init-param.view-template=/html/view.jsp",
"javax.portlet.init-param.edit-template=/html/edit.jsp",
"javax.portlet.name=" + GRPSignupPortletKeys.GRPSIGNUP,
"javax.portlet.resource-bundle=content.Language",
"javax.portlet.security-role-ref=administrator,guest,power-user,user"
},
service = Portlet.class
)
public class GRPSignupPortlet extends GenericPortlet {
...
...
}
So it's obviously possible, as the Login portlet works. I'm sure there is just some small bit of config I'm missing. I've tried to see what is different in the Liferay Login portlet that allows it to work, but haven't found the secret.
Liferay CE 7.3
You need to add the property 'add-default-resource'. In the component add:
"com.liferay.portlet.add-default-resource=true"
From portal.properties: "add-default-resource" set to true will allow those portlets to be dynamically added to any page by any user. This is useful (and necessary) for some portlets that need to be dynamically added to a page, but it can also pose a security risk because it also allows any user to do it.
It's prudent to also add
"com.liferay.portlet.add-default-resource-check-enabled=true",
From portal.properties: Set this property to true to add a security check around this behavior. If set to true, then portlets can only be dynamically added to a page if it contains a proper security token. This security token is automatically passed when using a portlet URL from one portlet to another portlet.

Using Trusted Web Activity to link multiple websites with native application

I've managed to link my native application to a website and launch the same on a button click. As the website is trusted, the URL bar is not visible. In the launched website there is a button which then further redirects to another website. I've created a digital asset link for both and have added the JSON file in <websitename>/.well-known/<json-file>.
Both the websites have also been referenced in strings.xml under
asset_statements. However, on launching the first website and then redirecting to the second website from the first, the second website launches as a regular custom chrome tab with the URL bar visible.
Is it possible to hide both the URL's? If so, how?
To enable multi-domain, you need to check 3 things
Each origin has a .well-known/assetlinks.json file
The android asset_statements contains all origins
Tell the Trusted Web Activity about additional origins when launching.
It seems you have the first two points covered, but not the last one.
Using the support library LauncherActivity:
If using the LauncherActivity that comes with the library, you can provide additional origins by updating the AndroidManifest:
Add a list of additional origins to res/values/strings.xml:
<string-array name="additional_trusted_origins">
<item>https://www.google.com</item>
</string-array>
Update AndroidManifest.xml:
<activity android:name="com.google.androidbrowserhelper.trusted.LauncherActivity"
android:label="#string/app_name">
<meta-data
android:name="android.support.customtabs.trusted.ADDITIONAL_TRUSTED_ORIGINS"
android:resource="#array/additional_trusted_origins" />
...
</activity>
Using a custom LauncherActivity
If using your own LauncherActivity, launching with additional origins can implemented like this:
public void launcherWithMultipleOrigins(View view) {
List<String> origins = Arrays.asList(
"https://checkout.example.com/"
);
TrustedWebActivityIntentBuilder builder = new TrustedWebActivityIntentBuilder(LAUNCH_URI)
.setAdditionalTrustedOrigins(origins);
new TwaLauncher(this).launch(builder, null, null);
}
Resources:
Article with more details here: https://developers.google.com/web/android/trusted-web-activity/multi-origin
Sample multi-origin implementation: https://github.com/GoogleChrome/android-browser-helper/tree/master/demos/twa-multi-domain

Why this script is only working in preview mode - Kentico

Why below script is only working in preview mode of Kentico CMS
{% Documents["/Page-Resource/Portfolio/Product-Marketo"].GetValue("Description") #%}
Actually had a issue with the macro permissions for document collections. In such case, disable the check by adding the following key to web.config file:
<add key="CMSCheckPermissionsForDocumentCollection" value="false"/>
Another option:
For the document you reference in your macro, go to Properties > Security, add "Public Anonymous User (public)" to the "Users and Roles" box, and check "Read" for their "Access rights". Click OK.

Adding script maps during installation of web application IIS

has anyone successfully added IIS script maps to their Wix installation. I have been using this:
<CustomAction Id="AddHandlers_Cmd" Property="AddHandlers" Value=""[SystemFolder]inetsrv\appcmd" set config -section:system.webServer/handlers /+"[\[]name='GSOAP',path='*.dll', verb='*',modules='IsapiModule',scriptProcessor='[BIN]mod_gsoap.dll',resourceType='File', requireAccess='Execute'[\]]"" Execute="immediate"/>
<CustomAction Id="AddHandlers" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="check" Impersonate="no"/>
However I get the 404 errors from my web application and when I add the script map manually after installing the application it works perfectly. I would appreciate if anyone could share how they done this.
It sounds like you need to add handler mapping to your web application. If that's the case, then you don't need a custom action to accomplish this.
Take a look at WebApplicationExtension element.
We are writing a separate Custom action in C# and Schedule it in after install Finalize to add handlers.
Try this, you can do anything with your own custom action.
I haven't worked with GSOAP handler, but used ASP.NET ISAPI extention. I suppose basically it has the same level of integration. I will post the code for ASP.NET and I hope you won't have problem with changing it to GSOAP. I have a huge risk of changing something incorrectly and make the examples unusable for you, so I let you do it better.
Here is my code to register extention itself if it isn't
<Component Id="Iis6ConfigExtentions" Guid="{GuidHash({ProductId}-1822E4F3-5850-47D5-9281-D1E0E20C77D4)}" KeyPath="yes" Permanent="yes">
<Condition><![CDATA[Installed OR (IISMAJORVERSION AND (IISMAJORVERSION = "#6"))]]></Condition>
<iis:WebServiceExtension Id="ExtensionASP4" Group="ASP.NET v4.0.30319" Allow="yes" File="[FRAMEWORKROOT]v4.0.30319\aspnet_isapi.dll" Description="ASP.NET v4.0.30319"/>
</Component>
and for adding those to the concrete site you need to use WebApplicationExtention, as #Yan already mentioned:
<iis:WebApplication Id="IIS6WebApp" Name="[SITE_APP_NAME]" WebAppPool="AppPool" >
<iis:WebApplicationExtension Verbs="GET,HEAD,POST" CheckPath="no" Script="yes" Executable="[FRAMEWORKROOT]v4.0.30319\aspnet_isapi.dll" />
</iis:WebApplication>
The CheckPath="no" is required on IIS 6 because we use ASP.NET MVC which doesn't map urls to files on disk. You might need it too since service address probably doesn't map to physical file.
UPDATE:
Looks like it is really not possible to do it directly in WIX (at least in 3.5 version). You are going in right direction - custom action using appcmd. But the provided custom actions aren't complete or what you need: the first one just sets property value to the command you need to execute and the second one calls some Dll custom action which wasn't provided.
What I'd try to execute is:
<CustomAction Id="AddGsoapHandler" Directory="TARGETDIR" Impersonate="no" Execute="deferred" Return="check" ExeCommand="[SystemFolder]inetsrv\appcmd.exe set config -section:system.webServer/handlers /+"[\[]name='GSOAP',path='*.dll', verb='*',modules='IsapiModule',scriptProcessor='[BIN]mod_gsoap.dll',resourceType='File', requireAccess='Execute'[\]]" /commit:apphost" />
Please pay attention to the path attribute of your handler configuration. It will limit handler usage to only URL's which ends with ".dll" - I just copied it from your code but not sure if you've done it intentionally or just copied from example at Microsoft site. That might have led to 401 error even if handler is registered successfully.
Also I added the /commit:apphost argument. Not sure if you really need this, but I use it to explicitly specify that I need to configure my application's config.
UPDATE 2:
If you need to set configuration to only single application, you should specify application object as argument of appcmd instead of the 'config' which means global configuration. Please try this:
<CustomAction Id="AddGsoapHandler" Directory="TARGETDIR" Impersonate="no" Execute="deferred" Return="check" ExeCommand="[SystemFolder]inetsrv\appcmd.exe set app "MySite/app1" -section:system.webServer/handlers /+"[\[]name='GSOAP',path='*.dll', verb='*',modules='IsapiModule',scriptProcessor='[BIN]mod_gsoap.dll',resourceType='File', requireAccess='Execute'[\]]" /commit:apphost" />
For more details you can read this tutorial.

Access Security level (ACL) with Java EE 6?

I am developing a web application where there are few roles like Admin,Reporter,Manager,Customer.Agent.Based on Role, some menu item need to be displayed . Admin can give permission (dynamically) to user say Agent ( which is not default permission ).Is there a better way to handle this situation ??
Thanks
You could have some controller which is responsible for permission logic. You would have a permission system where you can grant specific permissions to specific users / groups. The controller could be implemented as a jsf managed bean. You could have a method like this:
public boolean hasPermission(PermissionKey permissionKey) {
...
}
This method would check role + specific permissions.
PermissionKey, in this example, would be an enum, but you can make it a string or something else. Possible values would be, for example, "DELETE_ACCOUNT" or "HANDLE_PAYMENT".
In your views, you can just conditionnaly display components like this:
<h:outputText value="some text" rendered="#{authController.hasPermission('DELETE_ACCOUNT')}" />

Resources