Play Framework Authentication

Authentication LibraryPlay FrameworkScalaJavaWeb DevelopmentSecurity

Authentication Library

Play Framework Authentication

Overview

Play Framework Authentication is a built-in feature for implementing web application authentication in Play Framework applications. It provides basic authentication and authorization capabilities, with support for custom authentication scheme implementations.

Details

Play Framework Authentication is a simple and lightweight authentication system built into the Play Framework. While the framework doesn't provide a complete authentication mechanism out of the box, developers need to implement their own, but essential basic components are provided. Using Security.Authenticator patterns and Secure modules, you can implement basic security features like session management, CSRF protection, and XSS prevention. As of 2024, it's still possible to build robust authentication systems following security best practices, with flexible implementation according to custom requirements. It supports both Scala and Java languages and handles authentication for both RESTful APIs and web applications.

Pros and Cons

Pros

  • Framework Integration: Complete integration with Play Framework for consistent development experience
  • Session Management: Secure session management with signed sessions (non-encrypted)
  • CSRF Protection: Built-in Cross-Site Request Forgery (CSRF) protection
  • Customizable: Flexible implementation of authentication schemes according to requirements
  • Performance: Lightweight and fast authentication processing
  • Security: Automatic XSS escaping and security headers
  • Language Support: Support for both Scala and Java

Cons

  • Basic Features Only: Advanced authentication features need to be implemented manually
  • No Session Encryption: Session data is signed but not encrypted
  • External Dependencies: Complex authentication requirements need external libraries
  • Learning Curve: Need to learn Play Framework-specific authentication patterns
  • OAuth Support: OAuth/OpenID requires separate implementation or other libraries

Key Links

Usage Examples

Basic Authenticator Implementation

// Scala authentication implementation
import play.api.mvc._
import play.api.mvc.Security.Authenticator

class MyAuthenticator extends Authenticator {
  def getUsername(request: RequestHeader): Option[String] = {
    // Get username from session
    request.session.get("username")
  }
  
  def onUnauthorized(request: RequestHeader): Result = {
    // Redirect when unauthorized
    Results.Redirect(routes.AuthController.loginPage())
  }
}

// Usage in controller
@Security.Authenticated(new MyAuthenticator)
def protectedAction = Action { implicit request =>
  Ok(s"Hello, ${request.username}")
}

Session Management and Login

// Login processing
def login = Action { implicit request =>
  loginForm.bindFromRequest.fold(
    formWithErrors => {
      BadRequest(views.html.login(formWithErrors))
    },
    userData => {
      // User authentication processing
      if (authenticateUser(userData.email, userData.password)) {
        Redirect(routes.Dashboard.index())
          .withSession("username" -> userData.email)
      } else {
        BadRequest(views.html.login(loginForm.withGlobalError("Invalid credentials")))
      }
    }
  )
}

// Logout processing
def logout = Action {
  Redirect(routes.AuthController.loginPage())
    .withNewSession
    .flashing("info" -> "You have been logged out")
}

CSRF Protection Implementation

// CSRF token generation and verification
import play.filters.csrf._

def form = Action { implicit request =>
  Ok(views.html.form()(request, messagesProvider))
}

def submitForm = Action { implicit request =>
  // CSRF filter automatically validates
  CSRF.getToken match {
    case Some(token) => 
      // Form processing
      processForm(request)
    case None =>
      Forbidden("CSRF token missing")
  }
}

Java Authentication Implementation

// Java authentication implementation
import play.mvc.*;
import play.mvc.Security.*;

public class AuthAction extends Authenticator {
    @Override
    public String getUsername(Context ctx) {
        // Get username from session
        return ctx.session().get("username");
    }
    
    @Override
    public Result onUnauthorized(Context ctx) {
        // Redirect when unauthorized
        return redirect(routes.AuthController.login());
    }
}

// Usage in controller
@Security.Authenticated(AuthAction.class)
public Result dashboard() {
    String username = session("username");
    return ok("Welcome, " + username);
}

Custom Authentication Scheme

// API key authentication implementation example
class ApiKeyAuthAction extends ActionBuilder[Request, AnyContent] {
  override def invokeBlock[A](request: Request[A], block: Request[A] => Future[Result]): Future[Result] = {
    request.headers.get("X-API-Key") match {
      case Some(apiKey) if isValidApiKey(apiKey) =>
        block(request)
      case _ =>
        Future.successful(Unauthorized("Invalid API key"))
    }
  }
  
  private def isValidApiKey(key: String): Boolean = {
    // API key validation logic
    ApiKeyRepository.validate(key)
  }
}

// Usage example
def apiEndpoint = ApiKeyAuthAction { request =>
  Ok(Json.obj("data" -> "Protected API response"))
}

Security Filter Configuration

// Security configuration in application.conf
play.filters.enabled += "play.filters.csrf.CSRFFilter"
play.filters.enabled += "play.filters.headers.SecurityHeadersFilter"
play.filters.enabled += "play.filters.hosts.AllowedHostsFilter"

// CSRF configuration
play.filters.csrf {
  token.name = "csrfToken"
  contentType.blackList = ["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"]
}

// Security headers configuration
play.filters.headers {
  frameOptions = "DENY"
  xssProtection = "1; mode=block"
  contentTypeOptions = "nosniff"
  contentSecurityPolicy = "default-src 'self'"
}