Authentication via login dialog in Scout (RAP) - eclipse-rap

I'd like to have an authentication based on scouts default security concept found in https://wiki.eclipse.org/Scout/Concepts/Security.
What I've done:
I added the BasicSecurityFilter to the servers plugin.xml:
<extension name="" point="org.eclipse.scout.rt.server.commons.filters">
<filter aliases="/ /process /remotefiles /updatesite" class="org.eclipse.scout.http.servletfilter.security.BasicSecurityFilter" ranking="30"></filter>
</extension>
And activated it in the config.ini:
org.eclipse.scout.http.servletfilter.security.BasicSecurityFilter#active=true
org.eclipse.scout.http.servletfilter.security.BasicSecurityFilter#realm=Development
org.eclipse.scout.http.servletfilter.security.BasicSecurityFilter#users=TEST\=admin
On client side I added the InternalNetAuthenticator in the plugin.xml:
<extension point="org.eclipse.core.net.authenticator">
<authenticator class="org.eclipse.scout.rt.ui.rap.login.internal.InternalNetAuthenticator"</authenticator>
</extension>
And set it as default authenticator in the client Activator:
#Override
public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
InternalNetAuthenticator authenticator = new InternalNetAuthenticator();
InternalNetAuthenticator.setDefault(authenticator);
}
What happens:
BasicSecurityFilter.negotiate() is called when accessing the application (first load, e.g. http://localhost:8015/web)
InternalNetAuthenticator.getPasswordAuthentication() is called when the negotiation in the BasicSecurityFilter fails (this is when user and password are not found in the HTTP header, or user and password are invalid).
Opening a Dialog on RAP level (see InternalNetAuthenticator.showModalDialog(status, display)) is impossible, because Display.getDefault() or Display.getCurrent() always returns null.
This is because all UI operations (e.g. opening a dialog) MUST appear in the UIThread (see java-doc in Display.getDefault()).
The InternalNetAuthenticator is instantiated in the UIThread (see Activator.start()), but it isn't called in the UIThread! Why???
Returning a PasswordAuthentication object provides the credentials within the HTTP header to the next BasicSecurityFilter.negotiate() call.
BasicSecurityFilter.negotiate()is called again with the given credentials.
What fails:
So because of the fact, that the InternalNetAuthenticator.showModalDialog(status, display) isn't called in the UI-thread, it causes a NullPointerException:
java.lang.NullPointerException
at org.eclipse.scout.rt.ui.rap.login.internal.InternalNetAuthenticator.showModalDialog(InternalNetAuthenticator.java:102)
...
What I've already considered:
General information
https://wiki.eclipse.org/Scout/HowTo/3.9/Extending_the_login_dialog
https://wiki.eclipse.org/Scout/Concepts/Securit
UI-thread problem
https://www.eclipse.org/forums/index.php/t/440290/
https://www.eclipse.org/rap/developers-guide/devguide.php?topic=threads.html
I already tried to store the UI-thread when instantiating the Authenticator in the Activator.start() method by creating an own Authenticator and adding a parameter to the constructor like:
MyAuthenticator my_authenticator = new MyAuthenticator(Thread.currentThread());
But this causes an IllegelStateException or something like that. So the UI-thread is not accessible on this way.
Using the BasicSecurityFilter on RAP-level (in plugin.xml of the RAP bundle) makes it possible to use the systems default login dialog.
But I would like to have a custom SecurityFilter which have acces to other server side systems, so it must appear on server side and a RAP/client side SecurityFilter is no option!
Summary
All I can see is, that solving the Problem with the UI-thread will be the preferred way to move this issue forward.
I'll also accept alternative solutions to have a custom login dialog in my eclipse-scout-RAP environment.

Problem description:
If I've understood your use case correctly, you'd like to introduce something like a form-based authentication. I guess this is what you wanted to achieve with displaying the login dialog in the RAP UI-Thread.
Solution proposal:
Some steps were taken to introduce a form-based authentication to the Scout demo application BahBah chat that can be found at [1]. Please note that this example was based on an older Scout version (3.10).
In the following explaination, the implementation in [1] will be referred:
In [1], the approach was to make use of the facility of the Tomcat webcontainer to achieve a form-based authentication.
A sample HTML login page [2] can be found in the RAP UI bundle under the folder web-resources.
Therefore, in the plugin.xml [3] of the RAP application, the servlet filter BasicForwardSecurityFilter was removed. Make sure that the web-resources are accessible, e.g. under /res.
<extension point="org.eclipse.equinox.http.registry.resources">
<resource alias="/res" base-name="/web-resources"/>
</extension>
In the RAP application web.xml file the following entries were made.
<!-- Activate form-based authentication -->
<login-config>
<auth-method>FORM</auth-method>
<realm-name>BahBahJAASLogin</realm-name>
<form-login-config>
<form-login-page>/res/index.html</form-login-page>
<form-error-page>/res/index.html</form-error-page>
</form-login-config>
</login-config>
<!-- Define security role to access the application -->
<security-role>
<role-name>BahBahRolePrincipal</role-name>
</security-role>
<!-- static resources under /res/* should be accessible without requiring authentication -->
<security-constraint>
<web-resource-collection>
<web-resource-name>All Access</web-resource-name>
<url-pattern>/res/*</url-pattern>
<http-method>DELETE</http-method>
<http-method>PUT</http-method>
<http-method>HEAD</http-method>
<http-method>OPTIONS</http-method>
<http-method>TRACE</http-method>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<!-- Protect all other URLs of the application -->
<security-constraint>
<web-resource-collection>
<web-resource-name>Protected Resources</web-resource-name
<url-pattern>/web/*</url-pattern>
<url-pattern>/tablet/*</url-pattern>
<url-pattern>/mobile/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>BahBahRolePrincipal</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<!-- Define security filter and mapping -->
<filter>
<filter-name>BahbahSecurityFilter</filter-name>
<filter-class>com.bsiag.securityfilter.BahbahSecurityFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>BahbahSecurityFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
The BahbahSecurityFilter ensures that only authenticated principals are allowed to access the protected resources on the UI server.
In the doFilter method, the check is done by calling a method like:
// Taken from org.eclipse.scout.rt.server.commons.authentication.ServletFilterHelper#isRunningWithValidSubject(HttpServletRequest) see [4]
public boolean isRunningWithValidSubject(HttpServletRequest req) {
String username = req.getRemoteUser();
if (username == null || username.isEmpty()) {
return false;
}
Subject subject = Subject.getSubject(AccessController.getContext());
if (subject == null || subject.getPrincipals().isEmpty()) {
return false;
}
for (Principal principal : subject.getPrincipals()) {
if (username.equalsIgnoreCase(principal.getName())) {
return true;
}
}
return false;
}
In BahBahChat, a Realm [5] and a login module are configured to authenticate the users.
In particular, UserPrincipal and RolePrincipal are defined and also a LoginModule class is created.
In the Tomcat context.xml file the realm is configured.
<Realm className="org.apache.catalina.realm.JAASRealm"
appName="BahBahJAASLogin"
userClassNames="com.bsiag.securityfilter.BahBahUserPrincipal"
roleClassNames="com.bsiag.securityfilter.BahBahRolePrincipal"/>
Finally, the jaas.config file is defined:
BahBahJAASLogin {
com.bsiag.securityfilter.BahBahJAASLoginModule required debug=true;
};
The BahBahJAASLoginModule implements for the actual authentication process. A good example of setting up JAAS authentication in Tomcat can be found at [6]
Please also have a look at the Eclipse Scout forum post [7] that summarizes the necessary steps in a more generic way.
[1]
https://github.com/BSI-Business-Systems-Integration-AG/org.eclipsescout.demo/tree/features/kle/formBasedAuthentication
[2] org.eclipsescout.demo.bahbah.ui.rap/web-resources/index.html
[3] org.eclipsescout.demo.bahbah.ui.rap/plugin.xml
[4]
http://git.eclipse.org/c/scout/org.eclipse.scout.rt.git/tree/org.eclipse.scout.rt.server.commons/src/main/java/org/eclipse/scout/rt/server/commons/authentication/ServletFilterHelper.java?h=releases/5.2.x
[5] https://tomcat.apache.org/tomcat-7.0-doc/realm-howto.html
[6]
http://www.byteslounge.com/tutorials/jaas-authentication-in-tomcat-example
[7]
https://www.eclipse.org/forums/index.php?t=msg&th=821196&goto=1435976&#msg_1435976

Related

Best way to implement a button for the SP request to the IdP?

So I'm going to preface this by saying SAML (and user auth in general) is not my strong suit, so I apologize for any misused terminology.
Background:
We currently have an ASP.Net Framework website, using .Net version 4.7.2 (specifically webforms). Our website acts as a service provider (SP) and currently uses SAML 2.0 with a deprecated identity provider (IdP); luckily, this identity provider is getting replaced with Okta. The original IdP provided their own instructions for implementation which used OWIN middleware and their own NuGet package which configured SAML for us. With Okta though, I found we needed to use a different NuGet package. I've begun configuration for SAML using the SustainSys.Saml2 packages and made the suggested changes to the web.config (this is our preference over using their OWIN middleware, although I'm open to that, if there's a specific reason for it). For additional reference, here is the sustainsys documentation I was referencing.
Current Issue:
The web.config modifications and other changes (such as installing NuGets) have been completed and the website has been cleaned up so as not to cause any errors. However, my biggest question is how to tie it all together now. I understand that our website (the SP) needs to make a request to Okta (the IdP) for the SAML assertion. Unfortunately, I don't understand what I need to send in for that request. I was thinking just a hyperlink to the the IdP SSO link should work, but from what I've read about SAML, there would need to be some metadata related to that request. Can anyone suggest how to create a button that would send the necessary metadata? Or clarify if that even needs to be included (perhaps I've misunderstood what needs to be sent)? Also, any additional links or help pertaining to sustainsys (specifically, html or other display elements) would be hugely beneficial.
Thanks
To get the Sustainsys.Saml2 library to start the authentication process, you should use the Owin authentication infrastructure to initiate a challenge. That is a general Owin auth concept, and that is why it is not documented in the Sustainsys.Saml2 library.
Please see https://learn.microsoft.com/en-us/previous-versions/aspnet/dn343601(v=vs.113)
I tried to create a sample webform project and connected to Okta using Sustainsys Saml2 Owin middleware. The code below is just a POC that redirects from Webform Application's to OKTA sign-in page and returns the response back to the configured "Single Sign-On URL" in OKTA. The Code may not have all the necessary security layers. (Security Stamp, Validate Interval)
Login.aspx.cs
If there are more than one external login providers handle the code accordingly.
public partial class Login : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
IAuthenticationManager AuthenticationManager = HttpContext.Current.GetOwinContext().Authentication;
var loginProvider = AuthenticationManager.GetExternalAuthenticationTypes()
.FirstOrDefault();
AuthenticationManager.Challenge(loginProvider.AuthenticationType);
}
}
Screenshot of the SAML sent by Okta after successful authentication, captured using the Chrome extension
Startup.Auth.cs
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.UseSaml2Authentication(new Saml2AuthenticationOptions(true));
}
}
LoginCallback.cs
Again not completly sure on what code goes into the LoginCallback. But I just checked if the user is Authenticated.
public partial class LoginCallback : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
IAuthenticationManager AuthenticationManager = HttpContext.Current.GetOwinContext().Authentication;
bool isAuthenticated = AuthenticationManager.User.Identity.IsAuthenticated;
}
}

common services in asp.net core with razor pages

For reference, I have a common BasePageModel which inherits PageModel.
I also have several services I will ALWAYS use:
UserManager<AppUser> userManager
IHttpContextAccessor httpContextAccessor
IHostingEnvironment env
Is there a way to ALWAYS inject these so that I do not have to do constructor injection for each of these services on every single Razor Page?
In general, you can define a service to be injected into every view using _ViewImports.cshtml. Just add your view injection there, and the service will be available to every view.
However, you should not do that with any of the three services you explicitly mention. First, IHttpContextAccessor is unnecessary as you can get the HttpContext in your view via ViewContext.HttpContext. Likewise, IHostingEnvironment is mostly unnecessary as well, since you can use the environment tag helper:
<environment include="Development">
<p>This is development.</p>
</environment>
<environment exclude="Development">
<p>This is production.</p>
</environment>
For UserManager<AppUser>, it's better to only include such a service when you truly need it. If you find yourself doing the same logic over and over requiring this service, consider creating a tag helper or a view component instead to encapsulate that logic in a way that you can use it in multiple places without having to inject anything special into your view.
Finally, since the main point of this discussion was mostly about not sending email in development, the better approach there is to simply swap out the SMTP server with a something local in development. There's an app called Papercut which is open-source and free and makes sending/receiving email in development a breeze. By default, it will bind to localhost:25, so you'll just need to swap out your real SMTP connection with that. For example, you can create a section in your your appsettings.json like:
"Smtp": {
"Host": "localhost",
"Port": 25,
"EnableSsl": false,
"Username": "",
"Password": ""
}
Then, in your startup:
services.AddSingleton(_ => {
var config = Configuration.GetSection("Smtp").Get<SmtpConfig>();
return new SmtpClient
{
Host = config.Host,
Port = config.Port,
EnableSsl = config.EnableSsl,
Credentials = new NetworkCredential(config.Username, config.Password)
};
});
Then, simply inject SmtpClient into your email service, and you're off to the races. In production, you can use environment variables or Azure Key Vault to swap in your production SMTP connection settings. It's best not to use appsettings.json (or appsettings.Production.json) for this, as you'll most likely not want to commit it into your source control.

Publish App on windows 10 store with restricted namespace

I try to publish an App on windows 10 store, but I can not pass test from Windows App Certification Kit:
Restricted Namespace Error encountered: The restricted namespace test
Detected the following errors: Restricted Namespace found:
Impact if not corrected: The Windows Store does not allow an
Application manifest to refer to restricted namespaces. How to fix it:
Removes restricted namespaces from the application manifest.
But I use a restricted namespace for use SMS functions:
Xmlns: r = "http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
r: Capability Name = "cellularMessaging" />
How can made this changes to publish ?
You must also add the rescap namespace IgnorableNamespaces in the Package.appxmanifest file as shown below.
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap mp rescap">
<Capabilities>
<Capability Name="internetClient" />
<rescap:Capability Name="cellularMessaging" />
</Capabilities>
</Package>
When adding capabilities, keep them in the following order: 'Capability', 'rescap:Capability', then 'DeviceCapability', as there seems to be a problem when mixing them. (source)
Note that the app certification test will probably continue to fail. You need to request permission to actually use these capabilities.
Special and restricted capabilities are intended for very specific
scenarios. The use of these capabilities is highly restricted and
subject to additional Store onboarding policy and review. Follow the
steps below to request access to a restricted capability before
submitting your app to the store.
Determine if you are eligible to submit your app to the store with a
specific restricted capability by looking at the table below. If you
are not eligible, any requests you make will be denied.
If you are eligible visit the Submitting an App support page.
Set the problem type to App submission and certification and the category type to Submitting an app using a restricted capability.
Include the capability you are requesting access to and include a reason for your request. If you do not provide all the information necessary, your
request will be denied. You may also be asked to provide more
information.
Source

Bypass tomcat basic authentication using adobe flex

I have configured apache tomcat web.xml for basic authentication for specifc address by pasting code below in web.xml
<security-constraint>
<web-resource-collection>
<web-resource-name>
Protected Site
</web-resource-name>
<!-- This would protect the entire site -->
<url-pattern> /Documents/* </url-pattern>
<!-- If you list http methods,
only those methods are protected -->
<http-method> DELETE </http-method>
<http-method> GET </http-method>
<http-method> POST </http-method>
<http-method> PUT </http-method>
</web-resource-collection>
<auth-constraint>
<!-- Roles that have access -->
<role-name>role1</role-name>
</auth-constraint>
</security-constraint>
<!-- BASIC authentication -->
<login-config>
<auth-method> BASIC </auth-method>
<realm-name>Authentication </realm-name>
</login-config>
<!-- Define security roles -->
<security-role>
<description> Test role </description>
<role-name>role1</role-name>
</security-role>
I got browser basic authentication dialog for getting username and password. and after correct username and password i get authenticated and able to see document otherwise not.
Now every thing works fine but "I want to bypass this authentication using Adobe flex programming i.e by giving username N password in flex code, i want that this dialog should not appear and user gets authenticated by code."
You should add the authentication header to your service:HTTPService object.
import mx.utils.Base64Encoder;
private function addAuthenticationHeader(service:HTTPService):void
{
var encoder:Base64Encoder = new Base64Encoder();
encoder.insertNewLines = false;
encoder.encode("django:reinhardt");
service.headers = {Authorization:"Basic " + encoder.toString()};
service.send();
}
Edit: What do you want to achieve?
You want to get the result of the protected url in Flex
You want to somehow authenticate the user and then navigate (change the browser url) to the secured page ?
In my opinion 1 is not possible because Basic-Authentication (BA) does not rely on cookies or session id. If the browser does not re ask you the password on every protected pages this is just because it stores the BA header in an internal session that is not shared across all the page components especially with flash (for evident security reasons...).
If it is the second option then you should use such url that contains everything https//django:reinhardt#localhost/myApp/Documents/mySecret.mp3 and that will be mapped by the browser.
HIH
You can't do it in your Flex web application.
Only an AIR application or mobile app could do it -
because the following headers are not allowed for the former in URLRequestHeader:
Accept-Charset, Accept-Encoding, Accept-Ranges, Age, Allow, Allowed,
Authorization, Charge-To, Connect, Connection, Content-Length,
Content-Location, Content-Range, Cookie, Date, Delete, ETag, Expect,
Get, Head, Host, If-Modified-Since, Keep-Alive, Last-Modified,
Location, Max-Forwards, Options, Origin, Post, Proxy-Authenticate,
Proxy-Authorization, Proxy-Connection, Public, Put, Range, Referer,
Request-Range, Retry-After, Server, TE, Trace, Trailer,
Transfer-Encoding, Upgrade, URI, User-Agent, Vary, Via, Warning,
WWW-Authenticate, x-flash-version

Security in Spring MVC and JSON

I want to provide security one way or another for Sending and Getting JSON Data,but I don't know how to do this.
Our System has roles of users (System admin, General Members, etc.)
We decided send data as JSON using the Spring MVC URL pattern. I don't want everybody that outside from system to use this URL, only users can use the URL.
Example
www.example.com/services/"hereUserPass"/"hereUserName"/category/3
Each request time for different URLs, Should I control the username and password whether registered before? or What should I do for Security?
You want to implement security into your Spring Web application. You can do this at two ways:
Url Based Security
Method Based Security
Try to make another xml file as like applicationContext-security.xml Here is an example:
<http use-expressions="true">
<intercept-url pattern="/" access="permitAll"/>
<intercept-url pattern="/static/**" filters="none" />
<intercept-url pattern="/**" access="isAuthenticated()" />
<form-login />
<logout />
</http>
Here we see that permitAll means permit everybody who wants to reach that URL. filters = none has the same effect but it means that user will not go over Spring Security(Previous one goes over Spring Security but has access, filtering doesn't applied). isAuthenticated means that user can reach there if authenticated. You can also apply role based acces to urls.
Other security implementation base on middle tier security. You should add this line at your application context security file:
<global-method-security pre-post-annotations="enabled" />
so you can use method based security as like:
#PreAuthorize("hasRole('ROLE_SUPERVISOR')")
void storeVisit(Visit visit) throws DataAccessException;
You can start to reading with Spring Security implementation of Spring's Pet Clinic example: http://static.springsource.org/spring-security/site/petclinic-tutorial.html
Also I recommend you read here: http://www.mularien.com/blog/2008/07/07/5-minute-guide-to-spring-security/