devcon 2012 william boyd securing spring building blocks with blackboard security
DESCRIPTION
Client PresentationTRANSCRIPT
Securing Spring Building Blocks with Blackboard SecurityWilliam BoydSenior Software DeveloperLiberty University
2
Introduction – Why integrate Spring security and Blackboard security?
• Spring security offers many benefits• Can be as simple to use as you want it to be
• Robust• url-based security filtering
• method-level security
• Annotations
• fully customizable
• Spring security does a lot so you don’t have to
3
Introduction – Why integrate Spring security and Blackboard security?
• By using Blackboard’s security framework, we can take advantage of features that are already provided in Bb and already integrate with Bb
• Bb handles authentication and user information (using whatever authentication scheme you have selected)
• Bb already has context-based provisioning in place through the use of context-based roles and entitlements
• By integrating Bb’s security framework with Spring security, we can take advantage of both
4
Introduction – Sample of our end goal
• Pseudocode showing how easy it will be to handle security once we have everything set up
We want to secure this method so that only professors can use it
something_only_prof_can_do() {
do stuff;
}
5
Introduction – Sample of our end goal
• Pseudocode showing how easy it will be to handle security once we have everything set up
We want to secure this method so that only professors can use it
@Secured(“ONLY_LET_PROF_DO_THIS”)
something_only_prof_can_do() {
do stuff;
}
6
Introduction – Sample of our end goal
• This example shows method-level security using the @Secured annotation
• All of the other ways of doing security in Spring (such as url-based security) will be available as well
• You can use any method of securing your application, or even a mixture of multiple methods
7
Introduction – What we will cover
• What we need to do to integrate Spring/Bb authentication
• What we need to do to integrate Spring/Bb authorization
• What we can use from Bb for authorization
• How to create and use your own custom entitlements for your building block
8
Integrating Bb Security and Spring Security
• We will only cover a few relevant pieces of Spring security, there is plenty of documentation and more that it can do than I will show here
• Spring security documentation: http://static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity.html
• My sample project: https://dl.dropbox.com/u/16806953/BbSpringSecurityExample.zip
• Web application security generally happens in two parts1. Authentication – determining who the user is and ensuring
that they are who they say they are
2. Authorization – determining whether or not they should be able to access the resource they are trying to access
9
Integrating Spring Security with Bb Authentication
• Authentication usually consists of
1. A login process for users who are not logged in
2. Something to validate their session on subsequent requests
• By default, Spring security lets you set all this up with relative ease… but in our case Bb is already doing all of this (user is already logged in to Bb)
• So we need to get Spring to recognize this login and give it access to the info about the user that Bb already has
10
Integrating Spring Security with Bb Authentication – Spring security preauthentication• Spring security’s preauthentication setup allows us to
set up Spring security to make use of existing authentication mechanisms that it does not control (in this case Bb)
• Documentation on preauthentication: http://static.springsource.org/spring-security/site/docs/3.1.x/reference/preauth.html
11
Integrating Spring Security with Bb Authentication – Spring security preauthentication• When using preauthentication, there are multiple
places you can “hook into” in order to load the Bb authentication data into spring
• I wrote a custom AbstractPreAuthenticatedProcessingFilter which uses the Bb building blocks API to determine if the user is logged in and who they are• I could add more code to pull in more info about the user if I
wanted to
12
Integrating Spring Security with Bb Authentication BlackboardPreAuthenticatedProcessingFilterpublic class BlackboardPreAuthenticatedProcessingFilter extends AbstractPreAuthenticatedProcessingFilter {
@Override protected Object getPreAuthenticatedCredentials(HttpServletRequest request) { Context context = ContextManagerFactory.getInstance().getContext(); BbSession session = context.getSession(); if (context != null && session != null && context.getUser() != null && session.isAuthenticated()) { return context.getUser().getUserName(); } else { return null; } } @Override protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) { Context context = ContextManagerFactory.getInstance().getContext(); BbSession session = context.getSession(); if (context != null && session != null && session.isAuthenticated()) { return context.getUser(); } else { return null; } } }
13
Integrating Spring Security with Bb Authentication – Spring security preauthentication config
Inside my application context config:
<security:http auto-config="true" access-denied-page="/accessDeniedErrorPage" entry-point-ref="preAuthenticatedProcessingFilterEntryPoint" access-decision-manager-ref="accessDecisionManager" use-expressions="true"> <security:session-management session-fixation-protection="none" /> <security:custom-filter after="PRE_AUTH_FILTER" ref="blackboardPreAuthenticatedProcessingFilter"/> <security:anonymous/></security:http>
14
Integrating Spring Security with Bb Authentication – Spring security preauthentication config
<security:authentication-manager alias="authenticationManager"> <security:authentication-provider ref="preAuthenticatedAuthenticationProvider"/> </security:authentication-manager>
<bean id="preAuthenticatedAuthenticationProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider"> <property name="preAuthenticatedUserDetailsService" ref="preAuthenticatedUserDetailsService"/> </bean>
<bean id="preAuthenticatedUserDetailsService" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesUserDetailsService"/>
15
Integrating Spring Security with Bb Authentication – Spring security preauthentication config<bean id="blackboardPreAuthenticatedProcessingFilter" class="edu.liberty.lms.lublackboard.security.BlackboardPreAuthenticatedProcessingFilter"> <property name="authenticationManager" ref="authenticationManager"/> <property name="authenticationDetailsSource"> <bean class="org.springframework.security.web.authentication.preauth.j2ee.J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource"> <property name="mappableRolesRetriever"> <bean class="org.springframework.security.web.authentication.preauth.j2ee.WebXmlMappableAttributesRetriever" /> </property> <property name="userRoles2GrantedAuthoritiesMapper"> <bean class="org.springframework.security.core.authority.mapping.SimpleAttributes2GrantedAuthoritiesMapper"> <property name="convertAttributeToUpperCase" value="true"/> </bean> </property> </bean> </property> </bean>
16
Integrating Spring Security with Bb Authentication – Spring security preauthentication config
<bean id="preAuthenticatedProcessingFilterEntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>
17
Integrating Spring Security with Bb Authorization
• Authorization involves determining whether the current user should have access to the resource they are requesting
• Can be handled by any sort of logic, but usually handled through the concept of roles and/or permissions
• Documentation on Spring security authorization: http://static.springsource.org/spring-security/site/docs/3.1.x/reference/authorization.html
18
Integrating Spring Security with Bb Authorization
• There are multiple ways to apply security rules in Spring to define who has access to what
• Resources can be secured through expressions, which are just strings which are later interpreted by “voters”
Example expression: hasRole(‘admin’)
• How an expression gets interpreted depends entirely on what voters you use
• These expressions can be defined in multiple places. My preferred method is to use @Secured annotations on my controller methods (you just put the expression in the value of the @Secured annotation like @Secured(“hasRole(admin)”))
19
Integrating Spring Security with Bb Authorization
• In Spring security, AccessDecisionManager holds a list of Voters, which vote (yes/no/abstain) on whether or not to grant the user access
• Each voter checks each applicable expression and votes if that expression is recognized by that voter
• We want to be able to utilize information about roles/permissions in Bb in order to authorize users for resources in our building block, so I wrote a custom voter and added it to the list
20
Integrating Spring Security with Bb Authorization – custom voter config
<bean id="accessDecisionManager"
class="org.springframework.security.access.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions" value="false"/>
<property name="decisionVoters">
<list>
<bean class="org.springframework.security.access.vote.RoleVoter" />
<bean
class="org.springframework.security.access.vote.AuthenticatedVoter" />
<bean
class="edu.liberty.lms.lublackboard.security.BlackboardContextualRoleVoter" />
</list>
</property>
</bean>
21
Integrating Spring Security with Bb Authorization – custom voter config
<bean id="accessDecisionManager"
class="org.springframework.security.access.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions" value="false"/>
<property name="decisionVoters">
<list>
<bean class="org.springframework.security.access.vote.RoleVoter" />
<bean
class="org.springframework.security.access.vote.AuthenticatedVoter" />
<bean
class="edu.liberty.lms.lublackboard.security.BlackboardContextualRoleVoter" />
</list>
</property>
</bean>
22
Integrating Spring Security with Bb Authorization – inside the custom BlackboardContextualRoleVoter
supports() returns true if the config attribute (expression) can be interpreted
by this voter (this voter will try to interpret any attribute that starts with
“BB_”)
private static final String ATTRIBUTE_PREFIX = "BB_";
@Override
public boolean supports(ConfigAttribute attribute) {
if (attribute.getAttribute().startsWith(ATTRIBUTE_PREFIX)) {
return true;
} else {
return false;
}
}
23
Integrating Spring Security with Bb Authorization – inside the custom BlackboardContextualRoleVoter
vote() checks the collection of attributes (the expression strings) that the
voter can interpret and implements logic to determine whether or not
access should be granted
@Override
public int vote(Authentication authentication, Object object, Collection
attributes) {
…
}
24
Integrating Spring Security with Bb Authorization – inside the custom BlackboardContextualRoleVoterprivate static final String ATTRIBUTE_PREFIX = "BB_";
private static final String SYSTEM_ADMIN_ROLE = "SYSTEM_ADMIN_ROLE";
private static final String ENTITLEMENT_PREFIX = "ENTITLEMENT:";
if (attribute.startsWith(ATTRIBUTE_PREFIX) && attribute.length() > ATTRIBUTE_PREFIX.length()) {
String attributeCode = attribute.substring(ATTRIBUTE_PREFIX.length());
if (attributeCode.equals(SYSTEM_ADMIN_ROLE)) {
if (!bbUserService.currentUserHasSystemRole(User.SystemRole.SYSTEM_ADMIN)) {
return ACCESS_DENIED;
} else {
affirmatives++;
}
} else if (attributeCode.startsWith(ENTITLEMENT_PREFIX) && attributeCode.length() > ENTITLEMENT_PREFIX.length()) {
String entitlement = attributeCode.substring(ENTITLEMENT_PREFIX.length());
if (!bbUserService.currentUserHasEntitlementInCurrentContext(entitlement)) {
return ACCESS_DENIED;
} else {
affirmatives++;
}
}
}
25
Integrating Spring Security with Bb Authorization – inside the custom BlackboardContextualRoleVoterprivate static final String ATTRIBUTE_PREFIX = "BB_";
private static final String SYSTEM_ADMIN_ROLE = "SYSTEM_ADMIN_ROLE";
private static final String ENTITLEMENT_PREFIX = "ENTITLEMENT:";
if (attribute.startsWith(ATTRIBUTE_PREFIX) && attribute.length() > ATTRIBUTE_PREFIX.length()) {
String attributeCode = attribute.substring(ATTRIBUTE_PREFIX.length());
if (attributeCode.equals(SYSTEM_ADMIN_ROLE)) {
if (!bbUserService.currentUserHasSystemRole(User.SystemRole.SYSTEM_ADMIN)) {
return ACCESS_DENIED;
} else {
affirmatives++;
}
} else if (attributeCode.startsWith(ENTITLEMENT_PREFIX) && attributeCode.length() > ENTITLEMENT_PREFIX.length()) {
String entitlement = attributeCode.substring(ENTITLEMENT_PREFIX.length());
if (!bbUserService.currentUserHasEntitlementInCurrentContext(entitlement)) {
return ACCESS_DENIED;
} else {
affirmatives++;
}
}
}
26
Integrating Spring Security with Bb Authorization – inside the custom BlackboardContextualRoleVoterIn BbUserServiceImpl:
@Override
public boolean currentUserHasEntitlement(String entitlement) {
return SecurityUtil.userHasEntitlement(entitlement);
}
@Override
public boolean currentUserHasEntitlementInCurrentContext(String entitlement) {
try {
SecurityUtil.checkEntitlement(entitlement);
return true;
} catch (AccessException e) {
return false;
}
}
@Override
public boolean currentUserHasSystemRole(SystemRole systemRole) {
User currentUser = ContextManagerFactory.getInstance().getContext().getUser();
if (currentUser != null) {
return systemRole.equals(user.getSystemRole());
} else {
return false;
}
}
27
Integrating Spring Security with Bb Authorization
• I can put whatever king of logic I want in my voter in order to allow it to interact with Bb Security via Bb building blocks API calls
• To see what is possible using the Bb API, check the API docs (link goes to the SecurityUtil class which contains most of the useful stuff): http://library.blackboard.com/ref/6760ba98-8f24-44f2-8e65-0dcee799abb8/blackboard/platform/security/SecurityUtil.html
• And check tutorials on edugarage such as this: http://www.edugarage.com/display/BBDN/Building+Block+Security
28
Integrating Spring Security with Bb Authorization
• The end result of this is that I can do this:
@Secured(“BB_SYSTEM_ADMIN_ROLE”)
public String adminStuff() {
…
}
• Only users with a system role of system admin in Bb can access this method (otherwise they get an access denied page)
• I could add logic to check for any system role (even custom ones) or even course/org roles
29
Integrating Spring Security with Bb Authorization
• I can also do this:
@Secured(“BB_ENTITLEMENT:course.content.EDIT”)
public String entitlementStuff() {
…
}
• Only users with the course.content.VIEW entitlement within the current course can access this function
• You might use this to secure a method for editing a course content item, for example (I use it for methods for editing custom content items)
30
Integrating Spring Security with Bb Authorization
• I also configured some other built-in Spring security voters alongside my custom voter so I can make use of some of the expressions they evaluate
IS_AUTHENTICATED_ANONYMOUSLY – lets everyone in
isAuthenticated() – lets everyone in if they are authenticated
31
Custom Entitlements
• The edugarage tutorial talks about using Bb’s entitlements for authorization, but what if we need provisioning specific to our building block?
• You can create custom entitlements in your bb-manifest.xml
32
Custom Entitlements
<entitlements><entitlement uid=“organization.buildingblock.VIEW”
label=“New Custom Entitlement”template=“course.statistics.report.VIEW”type=“Course”/>
</entitlements>
uid – just a unique ID for your entitlement (this is what you use when checking to see if the user has this entitlement)
label – label in the Bb interface when assigning the entitlement to a role
template – an existing entitlement to build this one off of
type – system, personal, or course
33
Custom Entitlements
• Once you have created your custom entitlements, you can assign it to existing or custom roles in the system admin tab in Bb:
Users > system roles and course/organization roles
34
Resources
This presentation:
https://dl.dropbox.com/u/16806953/DevCon2012_bb_spring_security.pptx
Sample project: https://dl.dropbox.com/u/16806953/BbSpringSecurityExample.zip
35
We value your feedback!Please fill out a session evaluation.