Identity and Authorization

Back

Loading concept...

🏰 The Castle of Identity: Jakarta EE Security

Imagine your application is a magical castle. Not just anyone can walk in! You need guards, secret passwords, special badges, and clever rules to keep the bad guys out and let the good guys in.


🎭 What is Identity and Authorization?

Think of it like a birthday party:

  • Identity = Knowing WHO is at the door (Is that really Timmy?)
  • Authentication = Proving it’s really them (Timmy shows his invitation)
  • Authorization = Deciding what they can do (Timmy can eat cake, but only the birthday kid can open presents!)

In Jakarta EE, we have powerful tools to do all of this!


🗄️ Identity Stores: The Guest Book

An Identity Store is like a magical guest book that remembers everyone who’s allowed in the castle.

graph TD A["User Arrives"] --> B{Check Identity Store} B --> C["Database Store"] B --> D["Custom Store"] C --> E["User Found?"] D --> E E -->|Yes| F["Welcome In!"] E -->|No| G["Go Away!"]

Simple Idea:

  • Someone knocks on the door
  • You check your guest book
  • If their name is there with the right password, they can enter!

📊 Database Identity Store

This is like keeping your guest list in a notebook (database).

Real Example: Imagine a table in your notebook:

Username Password (hashed) Groups
alice abc123hash admin
bob xyz789hash user

Jakarta EE Code:

@DatabaseIdentityStoreDefinition(
    dataSourceLookup = "java:comp/DefaultDataSource",
    callerQuery =
        "SELECT password FROM users WHERE username = ?",
    groupsQuery =
        "SELECT role FROM user_roles WHERE username = ?"
)
@ApplicationScoped
public class AppConfig {
    // Configuration class
}

What’s happening here?

  1. We tell the system WHERE to find users (database)
  2. HOW to check passwords
  3. WHAT groups/roles they belong to

🎨 Custom Identity Store

Sometimes the notebook (database) isn’t enough. What if users log in with their fingerprint? Or a magic spell?

You build your OWN guest book!

@ApplicationScoped
public class MyCustomStore
    implements IdentityStore {

    @Override
    public CredentialValidationResult validate(
        Credential credential) {

        UsernamePasswordCredential upc =
            (UsernamePasswordCredential) credential;

        String username = upc.getCaller();
        String password = upc.getPasswordAsString();

        // Your custom magic here!
        if (checkMySpecialWay(username, password)) {
            return new CredentialValidationResult(
                username,
                Set.of("user", "premium")
            );
        }

        return CredentialValidationResult.INVALID_RESULT;
    }
}

Think of it like:

  • The default guest book checks names in a list
  • YOUR custom guest book might check if they know a secret handshake!

👑 Role-Based Access Control (RBAC)

Imagine your castle has different rooms:

  • Kitchen → Only cooks can enter
  • Throne Room → Only kings and queens
  • Garden → Everyone can visit!
graph TD A["User: Alice"] --> B{What Role?} B -->|admin| C["Can Access Everything"] B -->|user| D["Can Access Garden + Library"] B -->|guest| E["Can Only See Garden"]

The Magic Idea: Instead of checking “Is this Alice? Is this Bob?” every time, we ask: “Are they an ADMIN?”

Benefits:

  • ✅ Easy to manage (change role, not 100 rules)
  • ✅ Clear and simple
  • ✅ Same rules for everyone in a group

📜 Declarative Security: The Easy Way

“Declarative” means you DECLARE the rules with simple labels (annotations).

It’s like putting signs on doors:

  • 🚪 “ADMINS ONLY” sign on the Treasury
  • 🚪 “USERS WELCOME” sign on the Library
@Path("/admin")
@RolesAllowed("admin")
public class AdminResource {

    @GET
    @Path("/secrets")
    public String getSecrets() {
        return "Top secret admin stuff!";
    }
}

@Path("/public")
@PermitAll
public class PublicResource {

    @GET
    public String hello() {
        return "Hello everyone!";
    }
}

See how simple?

  • @RolesAllowed("admin") = Only admins allowed here!
  • @PermitAll = Everyone can come in!

🔧 Programmatic Security: The Flexible Way

Sometimes signs on doors aren’t enough. What if:

  • “Admins can see everything, but users can only see THEIR OWN stuff”
  • “Premium users get extra features”

You write code to check!

@Path("/profile")
public class ProfileResource {

    @Context
    private SecurityContext securityContext;

    @GET
    @Path("/{userId}")
    public String getProfile(
        @PathParam("userId") String userId) {

        // Get who's asking
        String currentUser = securityContext
            .getCallerPrincipal().getName();

        // Admins see anyone's profile
        if (securityContext.isCallerInRole("admin")) {
            return getAnyProfile(userId);
        }

        // Users only see their own
        if (currentUser.equals(userId)) {
            return getAnyProfile(userId);
        }

        // Otherwise, no way!
        throw new ForbiddenException("Not yours!");
    }
}

The Power:

  • You make decisions WHILE the code runs
  • More control, more flexibility!

🏷️ Security Annotations: The Label Collection

Jakarta EE gives you a toolbox of labels:

Annotation What It Does
@RolesAllowed Only these roles enter
@PermitAll Everyone welcome!
@DenyAll Nobody allowed (maybe for testing)
@RunAs Pretend to be another role

Example with all of them:

@Path("/api")
public class MixedResource {

    @GET
    @PermitAll
    @Path("/welcome")
    public String welcome() {
        return "Hi friend!";
    }

    @GET
    @RolesAllowed({"admin", "manager"})
    @Path("/reports")
    public String reports() {
        return "Sales: $1,000,000";
    }

    @DELETE
    @RolesAllowed("admin")
    @Path("/everything")
    public String deleteAll() {
        return "Everything deleted!";
    }

    @GET
    @DenyAll
    @Path("/forbidden")
    public String forbidden() {
        return "You'll never see this!";
    }
}

🛡️ CSRF Protection: Stop the Tricksters!

CSRF = Cross-Site Request Forgery

Imagine this sneaky trick:

  1. You’re logged into your bank
  2. A bad website secretly makes YOUR browser send money to the bad guy
  3. The bank thinks it’s really you!
graph TD A["You're Logged In] --> B[Bad Website] B -->|Secret Request| C[Your Bank] C -->|Thinks It's You!| D[Money Gone!"]

The Solution: Secret Tokens!

Like a secret handshake that changes every time:

<!-- In your form -->
<form method="POST" action="/transfer">
    <input type="hidden"
           name="csrf_token"
           value="abc123xyz789">
    <input type="text" name="amount">
    <button>Send Money</button>
</form>
// Server checks the token
@POST
@Path("/transfer")
public Response transfer(
    @FormParam("csrf_token") String token,
    @FormParam("amount") int amount) {

    if (!isValidCsrfToken(token)) {
        return Response.status(403)
            .entity("Nice try, trickster!")
            .build();
    }

    // Safe to proceed!
    return doTransfer(amount);
}

How tokens work:

  1. 🎫 Server gives you a SECRET token
  2. 📝 Your form includes this token
  3. ✅ Server checks: “Is this the token I gave YOU?”
  4. 🚫 Bad websites can’t guess your token!

🎯 Putting It All Together

Let’s build a mini secure castle:

// 1. Define where users come from
@DatabaseIdentityStoreDefinition(
    dataSourceLookup = "java:comp/DefaultDataSource",
    callerQuery = "SELECT password FROM users WHERE name = ?",
    groupsQuery = "SELECT role FROM roles WHERE name = ?"
)

// 2. Set up authentication
@BasicAuthenticationMechanismDefinition(
    realmName = "MyCastle"
)

@ApplicationScoped
public class SecuritySetup {}

// 3. Protect your resources
@Path("/castle")
public class CastleAPI {

    @GET
    @Path("/gate")
    @PermitAll
    public String gate() {
        return "Welcome to the castle gates!";
    }

    @GET
    @Path("/treasury")
    @RolesAllowed("king")
    public String treasury() {
        return "Gold coins everywhere!";
    }

    @GET
    @Path("/kitchen")
    @RolesAllowed({"cook", "king"})
    public String kitchen() {
        return "Delicious food cooking!";
    }
}

✨ Key Takeaways

  1. Identity Stores = Your guest list (database or custom)
  2. Database Store = Names in a notebook/database
  3. Custom Store = Your own special way to check
  4. RBAC = Group people by roles, not names
  5. Declarative = Put signs on doors (@RolesAllowed)
  6. Programmatic = Write code to decide
  7. Annotations = Your label toolbox
  8. CSRF Protection = Secret tokens stop tricksters

🚀 You Did It!

Now you know how to:

  • ✅ Know WHO is knocking (Identity Stores)
  • ✅ Group them smartly (Roles)
  • ✅ Put up signs (Declarative)
  • ✅ Make smart decisions (Programmatic)
  • ✅ Stop sneaky tricks (CSRF)

Your castle is SECURE! 🏰🔐

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.