Grails Spring LDAP Security multiple domain use case - spring

I have several DC in my LDAP(like DC=Ny, DC=Oh) and would like to authenticate the user from LDAP through grails spring ldap plugin.
Initially I have used following parameters in the config.groovy file and was able to authenticate the users from newyork but now I have to authenticate the users from both newyork and Ohio.
// Added by the Spring Security Core plugin:
grails.plugins.springsecurity.userLookup.userDomainClassName = 'com.test.SecUser'
grails.plugins.springsecurity.userLookup.authorityJoinClassName = 'com.test.SecUserSecRole'
grails.plugins.springsecurity.authority.className = 'com.test.SecRole'
// LDAP config
grails.plugins.springsecurity.ldap.context.managerDn = 'CN=P8,OU=P8,OU=Weblogic,OU=PR,OU=Groups - Application,DC=NY,DC=GWL,DC=com'
grails.plugins.springsecurity.ldap.context.managerPassword = 'test'
grails.plugins.springsecurity.ldap.context.server = 'ldap://NY.GWL.com:389/'
grails.plugins.springsecurity.ldap.authorities.ignorePartialResultException = true // typically needed for Active Directory
grails.plugins.springsecurity.ldap.search.base = 'DC=NY,DC=GWL,DC=com'
grails.plugins.springsecurity.ldap.search.filter="sAMAccountName={0}" // for Active Directory you need this
grails.plugins.springsecurity.ldap.search.searchSubtree = true
grails.plugins.springsecurity.ldap.auth.hideUserNotFoundExceptions = false
grails.plugins.springsecurity.ldap.search.attributesToReturn = ['mail', 'displayName'] // extra attributes you want returned; see below for custom classes that access this data
grails.plugins.springsecurity.providerNames = ['ldapAuthProvider', 'anonymousAuthenticationProvider'] // specify this when you want to skip attempting to load from db and only use LDAP
What kind of changes needs to be done in groovy.config file or does I need to do any code changes.
Any help on this will be really helpful.
Thanks

Related

Sabre Integration for CalDAV

I'm working on a web-based scheduling application that needs to integrate iCloud Calendar into it. Unlike Google Calendar and Microsoft Outlook, I came to know that iCloud doesn't provide any APIs for integration. So, I came to know about Sabre CalDAV.
But instead of progressing, I got stuck into its comprehensive documentation. Does anyone have proper documentation or could help me out with authenticating: Sabre\DAV\Auth\Backend\Apache(https://sabre.io/dav/caldav/) for Authentication.
Also, I need to CalDAV plugin but it may require authentication first.
Please find below as my server.php code:
<?php
use
Sabre\DAV,
Sabre\CalDAV,
Sabre\DAVACL;
$pdo = new \PDO('sqlite:data/db.sqlite');
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
//Mapping PHP errors to exceptions
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler("exception_error_handler");
// Files we need
require_once 'vendor/autoload.php';
// Backends
$authBackend = new DAV\Auth\Backend\PDO($pdo);
$principalBackend = new DAVACL\PrincipalBackend\PDO($pdo);
$calendarBackend = new CalDAV\Backend\PDO($pdo);
// Directory tree
$tree = array(
new DAVACL\PrincipalCollection($principalBackend),
new CalDAV\CalendarRoot($principalBackend, $calendarBackend)
);
// The object tree needs in turn to be passed to the server class
$server = new DAV\Server($tree);
// You are highly encouraged to set your WebDAV server base url. Without it,
// SabreDAV will guess, but the guess is not always correct. Putting the
// server on the root of the domain will improve compatibility.
$server->setBaseUri('/sabre/server.php');
// Authentication plugin
$authPlugin = new DAV\Auth\Plugin($authBackend,'SabreDAV');
$server->addPlugin($authPlugin);
// CalDAV plugin
$caldavPlugin = new CalDAV\Plugin();
$server->addPlugin($caldavPlugin);
// CardDAV plugin
$carddavPlugin = new CardDAV\Plugin();
$server->addPlugin($carddavPlugin);
// ACL plugin
$aclPlugin = new DAVACL\Plugin();
$server->addPlugin($aclPlugin);
// Support for html frontend
$browser = new DAV\Browser\Plugin();
$server->addPlugin($browser);
// And off we go!
$server->exec();

How to implement versioning for Token endpoint in Web API 2

I have a Asp.Net Web API 2 using Token based authentication (OAuth2).
I have implemented Web API versioning using aspnet-api-versioning.
So now I have three different versions of my API. It's really great, I can now change V3 without affecting the current API.
But the /token endpoint is not versioned because it is not in my controller. It's in the Providers.
I searched but couldn't find anything helpful.
We can register more than one token endpoint in the Startup.Auth.cs
So here's what I did:
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AuthorizeEndpointPath = new PathString("/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(TokenExpirationInDays),
AllowInsecureHttp = true, //Allow HTTP to send username password.
};
app.UseOAuthBearerTokens(OAuthOptions);
OAuthOptionsV3 = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/api/V3/Accounts/Token"),
Provider = new ApplicationOAuthProvider2(PublicClientId),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(TokenExpirationInDays),
AllowInsecureHttp = true, //Allow HTTP to send username password.
};
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptionsV3);
So now I have different token endpoint for each version.
I'm not familiar with this particular setup, but this looks like middleware. There isn't quite enough information here to provide you with a specific answer, but your goals should be achievable in one of a few ways:
Option 1 - Use the Conventions API
If you authorization endpoint is actually a controller (though I think it is not), you can use the Conventions API like so:
services.AddApiVersioning(options =>
{
options.Conventions.Controller<OAuthController>().IsApiVersionNeutral();
}
Conventions was specifically meant to deal with a scenario where a controller might be externally defined and you don't have any control over the source code.
Option 2 - Use a Custom Convention
Middleware could create actions dynamically. As long as actions are actually produced, then you can use a custom IControllerConvention. You would be passed the ControllerModel which contains the actions you need to version. Assuming this is the correct behavior, you'd be looking for matching actions in the source model and then you can apply it to the controller conventions with something like:
public class MyConventions : IControllerConvention
{
public bool Apply(IControllerConventionBuilder controller, ControllerModel controllerModel)
{
var method = // TODO: resolve the target method from controllerModel
if (method == null)
{
return false;
}
controller.Action(method).IsApiVersionNeutral();
return false;
}
}
Option 3 - In Middleware
If this is pure middleware, API versioning isn't directly supported there. You can, however, support versioning on your own if the pipeline is composed properly. Specifically, API Versioning must come before other parts of middleware that need it. This usually happens automatically, but if you need to control registration, you need to change your setup to handle it manually like this:
services.AddApiVersioning(options => options.RegisterMiddleware = false);
// ... inside application setup
services.UseApiVersioning();
The API Versioning middleware doesn't really do much of anything special. It merely adds a pipeline feature. As long as that's before your other middleware, it will be available downstream like this:
var feature = context.Features.Get<IApiVersioningFeature>();
// the raw, unparsed API version, if any
var rawApiVersion = feature.RawApiVersion;
// the parse API version; will be null if no version is specified
// or the value cannot be parsed
var apiVersion = feature.ApiVersion;
// TODO: enforce versioning policies within the middleware
Option 4 - Use the API Explorer
If none of the previous approaches will work for you, you can leverage the API Explorer extensions for API Versioning to build your configuration (as above) from discovered APIs. This would have the advantage of not being hardcoded or require changes every time you release a new version.
Your application startup configuration would change to something like this:
public void Configure(IApplicationBuilder app, IApiVersionDescriptionProvider provider)
{
foreach (var description in provider.ApiVersionDescriptions)
{
var options = new OAuthAuthorizationServerOptions()
{
TokenEndpointPath = new PathString($"/api/{description.GroupName}/Accounts/Token"),
Provider = new ApplicationOAuthProvider2(PublicClientId),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(TokenExpirationInDays),
AllowInsecureHttp = true,
};
app.UseOAuthBearerTokens(options);
}
}

Grails Spring Security REST + LDAP

I am trying to set up Spring Security in Grails authenticating with a token (via the Spring Security REST plugin) and authorizing against LDAP. I have found several examples (I have about 20 browser tabs open right now), but none of them answer the whole question. Most of the examples are Grails + REST Security or Grails + LDAP Security, but no examples of Grails + REST + LDAP.
My issue is that the application tries to look in the database for users and roles, when I need it to look to LDAP.
I found the solution was to go into resources.groovy and configure the userDetailsService bean to use LDAP instead.The only "prerequisite" is that you must already have correct LDAP configurations to your LDAP server. I found this solution here: http://swordsystems.com/2011/12/21/spring-security-cas-ldap/. And only took the following piece.
// Place your Spring DSL code here
import grails.plugin.springsecurity.SpringSecurityUtils
beans = {
def config = SpringSecurityUtils.securityConfig
if (config.ldap.context.server) {
SpringSecurityUtils.loadSecondaryConfig 'DefaultLdapSecurityConfig'
config = SpringSecurityUtils.securityConfig
initialDirContextFactory(org.springframework.security.ldap.DefaultSpringSecurityContextSource,
config.ldap.context.server){
userDn = config.ldap.context.managerDn
password = config.ldap.context.managerPassword
}
ldapUserSearch(org.springframework.security.ldap.search.FilterBasedLdapUserSearch,
config.ldap.search.base,
config.ldap.search.filter,
initialDirContextFactory){
}
ldapAuthoritiesPopulator(org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator,
initialDirContextFactory,
config.ldap.authorities.groupSearchBase){
groupRoleAttribute = config.ldap.authorities.groupRoleAttribute
groupSearchFilter = config.ldap.authorities.groupSearchFilter
searchSubtree = config.ldap.authorities.searchSubtree
rolePrefix = "ROLE_"
convertToUpperCase = config.ldap.mapper.convertToUpperCase
ignorePartialResultException = config.ldap.authorities.ignorePartialResultException
}
userDetailsService(org.springframework.security.ldap.userdetails.LdapUserDetailsService,
ldapUserSearch,
ldapAuthoritiesPopulator){
}
}
}

Binding container managed authentication alias with DataSource using jython script

I'm using WebSphere 8.5
I've found out how to create JAASAuthData with username and password using jython script:
objServerAttrs = AdminControl.completeObjectName('WebSphere:type=Server,*')
cellName = AdminControl.getAttribute(objServerAttrs, 'cellName')
sec = AdminConfig.getid('/Cell:%s/Security:/' % cellName)
jaasAttr = [['alias', jaasAlias],['userId', jaasUser],['password', jaasPass]]
jaasAuthData = AdminConfig.create('JAASAuthData', sec, jaasAttr)
and how to create dataSource:
dsAttrs = [['name', 'myDS1'], ['jndiName','jdbc/MY/DS1']]
newDs = AdminConfig.create('DataSource', provider, dsAttrs)
Now I need to bind that JAASAuthData with my DataSource as 'Container-managed authentication alias', unfortunatelly I can't find anything in API, inspecting attributes of existing DataSources or any example for that task. How to create such binding?
You need to specify authDataAlias attribute:
dsAttrs = [['name', 'myDS1'], ['jndiName','jdbc/MY/DS1'], ['authDataAlias',jaasAlias]]
newDs = AdminConfig.create('DataSource', provider, dsAttrs)
The recommended way of configuring container-managed authentication alias is to set it on a resource reference during your application deployment.
It is still allowed (although deprecated) to configure it on DataSource level:
newDs = AdminConfig.create('DataSource', provider, dsAttrs)
mapping = AdminConfig.showAttribute(newDs, 'mapping')
AdminConfig.modify(mapping, [['mappingConfigAlias', jaasAlias], ['authDataAlias', jaasAlias]])
BTW: Your script would be more maintainable if you used WDR library http://wdr.github.io/WDR/ (I'm one of the main contributors).
jaasAlias = 'TheAuthAliasName'
provider = getid1('/JDBCProvider:TheProviderName/')
security = getid1('/Cell:/Security:/')
security.assure('JAASAuthData', {'alias':jaasAlias}, userId = 'user', password = 'password')
ds = provider.assure('DataSource', {'name':'myDS1'}, jndiName = 'jdbc/MY/DS1')
# component-managed authentication:
ds.authDataAlias = jaasAlias
# ... and container-managed authentication:
ds.mapping.mappingConfigAlias = jaasAlias
ds.mapping.authDataAlias = jaasAlias
save()
sync()
The above script can be safely re-run without failure or duplicate objects.

How to control direct url access?

How to control direct url access in jsf 2.0, struts 2 and spring 3 ? I mean not login user type url and display always home or login page.
You can either use a project like spring-security to integrate with your application, or write your own servlet-filter
The stackoverflow servlet-filter tag has a good overview of servlet filters. For most servlet compatible web frameworks you can integrate a filter to intercept requests and redirect invalid or unauthorized requests to where they belong.
I suggest you to use Apache Shiro filter for control direct access for a certain url.
Look at the Apache Shiro configuration ini file where are the control of url access shown.
[main]
logout = org.apache.shiro.web.filter.authc.LogoutFilter
roles = org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
authc.loginUrl=/faces/login.xhtml
authc.successUrl=/faces/index.xhtml
roles.unauthorizedUrl = /faces/unauthorized.xhtml
logout.redirectUrl = /faces/login.xhtml?status=loggedOut
jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.permissionsLookupEnabled = true
jdbcRealm.authenticationQuery = SELECT PASSWORD FROM USERS WHERE USERS.USERNAME = ?
jdbcRealm.userRolesQuery = SELECT ROLE_NAME FROM ROLES, USER_ROLE, USERS WHERE ROLES.ROLE_ID = USER_ROLE.ROLE_ID AND USERS.USR_ID = USER_ROLE.USR_ID AND USERS.USERNAME = ?
jdbcRealm.permissionsQuery = SELECT PERMISSIONS.PERM_NAME FROM ROLES, PERMISSIONS_ROLE, PERMISSIONS WHERE ROLES.ROLE_ID = PERMISSIONS_ROLE.ROLE_ID AND PERMISSIONS.PERM_ID = PERMISSIONS_ROLE.PERM_ID AND ROLES.ROLE_NAME = ?
ds = com.mysql.jdbc.jdbc2.optional.MysqlDataSource
ds.user = maqraa
ds.password = maqraa
ds.databaseName = maqraa
ds.serverName = localhost
ds.portNumber = 3306
jdbcRealm.dataSource = $ds
securityManager.realms = $jdbcRealm
[urls]
/faces/login.xhtml = authc
/faces/admin/** = authc, roles[admin]
/faces/teacher/** = authc, roles[teacher]
/faces/reports/** = authc, roles[admin]
/faces/officer/** = authc, roles[officer]
/faces/manager/** = authc, roles[manager]
/faces/roles/** = authc, roles[admin]
Looking at the previous url(s) you will find out that any access for /faces/login.xhtml must be done by authenticated user in addition to access some of url(s) you must be a playing for a specific role(s).
Review Shiro tag on stackoverflow or see the Apache Shiro site.
I hope that help you.
Thanks.

Resources