SecureSocial provides a replacement for Play's buit in Action class named SecuredAction
. This action intercepts requests and checks if there is an authenticated user. If there is one the execution continues and your code is invoked, if not the request is redirected to a login page. For ajax calls you can make SecureSocial return an unauthorized error instead of a redirect.
There is also a UserAwareAction
that can be used in actions that need to know if there is a current user but can be executed even if there isn't one.
Here's a sample usage in Scala:
// 1) add the SecureSocial trait to your controller
object Application extends Controller with securesocial.core.SecureSocial {
// 2) change Play's Action with SecuredAction
def index = SecuredAction { implicit request =>
Ok(views.html.index(request.user))
}
def page = UserAwareAction { implicit request =>
val userName = request.user match {
case Some(user) => user.fullName
case _ => "guest"
}
Ok("Hello %s".format(userName))
}
// you don't want to redirect to the login page for ajax calls so
// adding a ajaxCall = true will make SecureSocial return a forbidden error
// instead.
def ajaxCall = SecuredAction(ajaxCall = true) { implicit request =>
// return some json
}
// You can also use SecuredAction.async for async actions
def asyncAjaxCall = SecuredAction(ajaxCall = true).async { implicit request =>
// return a Future[SimpleResult] with some json
}
}
Note that you get access to the current user in the request using request.user
. This points to an instance of the Identity
trait for SecuredAction
and to an Option[Identity]
for UserAwareAction
.
In Java, you use annotations:
public class Application extends Controller {
@SecureSocial.SecuredAction
public static Result index() {
Identity user = (Identity) ctx().args.get(SecureSocial.USER_KEY);
return ok(index.render(user));
}
@SecureSocial.UserAwareAction
public static Result userAware() {
Identity user = (Identity) ctx().args.get(SecureSocial.USER_KEY);
final String userName = user != null ? user.fullName() : "guest";
return ok("Hello " + userName);
}
@SecureSocial.SecuredAction(ajaxCall = true)
public static Result ajaxCall() {
// return some json
}
}
The current user (always present for SecuredAction
) is available in the request context arguments.
The Identity
is defined using a trait (traits are similar to Java interfaces). The following attributes are defined in this trait:
identityId
: a IdentityId
object that stores the user userId
within the provider used to authenticate the user (eg: the twitter id) and the providerId
. firstName
, lastName
and fullName
: The user's names.email
: The user email address (available if the external service provides it). Eg: Twitter does not expose email addresses.avatarUrl
: The url that points to the user image in the authenticating service.Depending on how the user authenticated the following will be available too:
oAuth1Info
: an instance of OAuth1Info
containing the token
and secret
.oAuth2Info
: an instance of OAuth2Info
containing the accessToken
and optionals tokenType
, expiresIn
and refreshToken
values.passwordInfo
: an instance of PasswordInfo
containing the hashed password
and optinally the salt
used to hash it.For OAuth based logins the info fields should have all the information needed to invoke APIs on those external services.
As mentioned above, Identity
is defined using Scala. From Java, you see this trait as an interface and can access the attributes as if they were methods.
For example:
// accessing the first name
String msg = "Hello " + user.firstName()
Some attributes in Identity
such as email
or oAuth1Info
are defined using an Option
. In Scala, it is very common to use an Option
to model an optional value instead of leaving it null as in Java.
To access these attributes you need to first check if the Option
has a value in it (the equivalent to checking if it's null in Java).
For example:
String email = user.email().isDefined() ? user.email().get() : "Not available"
if ( user.oAuth1Info().isDefined() ) {
// there is a value
OAuth1Info info = user.oAuth1Info().get()
}