Here is a "fuller" one...
I usually have to hack that top bar to pieces...
I use Keycloak for auth and that works with JEE Security as I am using wildfly app server.... so role works!
KISS!
This does simple login/logout/show profile info etc.
Logging in is done by Keycloak intercepting ANY move to a protected page and it throws up the login challenge... (in fact for me anything under /pages/* is protected by Keycloak).
ANYHOW:
This may be useful in a few months when I am hunting again!
Code: Select all
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:pa="http://primefaces.org/atlantis">
<div class="topbar">
<!--
<div class="logo">
<p:graphicImage name="images/logo.png" library="atlantis-layout" />
</div>
<p:graphicImage name="images/appname.svg" library="atlantis-layout" styleClass="app-name"/>
-->
<!-- style="background-color: white" -->
<!-- <div class="logo">
<p:graphicImage name="images/brand/icon 120x70.svg" library="xxxxx-layout" />
</div>
-->
<div class="logo" style="margin-top:-16px; height: 80px">
<p:outputLabel style="font-size: 32pt; color:white">
<i class="fa fa-globe"></i>
</p:outputLabel>
</div>
<!--
<p:graphicImage name="images/brand/XXXXX.png" library="xxxxxx-layout" styleClass="app-name" style="height:100%"/>
-->
<span style="font-size: 22pt; color: white; font-weight: bolder; padding-left: 20px">XXXXXXX</span>
<a id="topbar-menu-button" href="#">
<i class="fa fa-bars"></i>
</a>
<ul class="topbar-menu fadeInDown animated">
<li class="profile-item">
<a href="#">
<div class="profile-info">
<span class="topbar-item-name profile-name">#{securityController.name}</span>
<h:outputText id="user-role" styleClass="topbar-item-name profile-role" value="#{securityController.role}"></h:outputText>
<p:tooltip for="user-role" value="#{securityController.roles}" position="bottom" trackMouse="true" />
</div>
</a>
</li>
<li>
<h:form id="LoginForm" rendered="#{!facesContext.externalContext.isUserInRole('uma_authorization')}">
<i style="color:white; vertical-align:middle" class="fa fa-fw fa-sign-in"></i>
<p:commandButton actionListener="#{securityController.login()}" style="color:white; vertical-align:middle" value="Login" />
</h:form>
</li>
<li>
<h:form id="ProfileForm" rendered="#{facesContext.externalContext.isUserInRole('uma_authorization')}">
<i style="color:white; vertical-align:middle" class="fa fa-fw fa-user"></i>
<p:commandButton actionListener="#{securityController.profile()}" style="color:white; vertical-align:middle" value="Profile" />
</h:form>
</li>
<li>
<h:form id="logoutForm" rendered="#{facesContext.externalContext.isUserInRole('uma_authorization')}">
<i style="color:white; vertical-align:middle" class="fa fa-fw fa-sign-out"></i>
<p:commandButton action="#{securityController.logout()}" style="color:white; vertical-align:middle" value="Logout" />
</h:form>
</li>
</ul>
</div>
</ui:composition>
here is the backing bean... but obviously you need a keycloak running with a realm set up...
Code: Select all
import java.io.Serializable;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Inject;
import javax.inject.Named;
@Named
@ViewScoped
public class HomeController implements Serializable {
private static final long serialVersionUID = 2615773142108848634L;
@Inject
private Logger logger;
@PostConstruct
public void init() {
logger.info("Home Controller (View Scoped)");
}
public String join() {
logger.info(">join");
logger.info("<join");
return "/pages/join?faces-redirect=true";
}
public String donate() {
logger.info(">donate");
logger.info("<donate");
return "/donate?faces-redirect=true";
}
}
Code: Select all
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Logger;
import java.io.IOException;
import java.io.Serializable;
import java.security.Principal;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.keycloak.KeycloakPrincipal;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.representations.IDToken;
@Named
@SessionScoped
public class SecurityController implements Serializable {
private static final long serialVersionUID = 3893061551568273021L;
@Inject
private HttpServletRequest request;
@Inject
private Logger logger;
@Inject
private TokenController tokenController;
@PostConstruct
public void init() {
logger.info("Security Controller (Session Scoped)");
}
public void login() throws IOException {
logger.info(">login");
logger.info("<login");
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
externalContext.redirect("http://localhost:8080/theplanetsparty/pages/my/dashboard.jsf");
}
public String logout() throws ServletException {
logger.info(">logout");
if (request.getUserPrincipal() != null) {
logger.info("Logging out: " + request.getUserPrincipal().getName());
Principal principal = request.getUserPrincipal();
if (principal instanceof KeycloakPrincipal) {
KeycloakPrincipal<KeycloakSecurityContext> kp = (KeycloakPrincipal<KeycloakSecurityContext>) principal;
// boolean hasPermission = kp.getKeycloakSecurityContext().getAuthorizationContext().hasPermission(arg0, arg1);
// boolean hasResourcePermission = kp.getKeycloakSecurityContext().getAuthorizationContext().hasResourcePermission(resourceName);
// boolean hasScopePermission = kp.getKeycloakSecurityContext().getAuthorizationContext().hasScopePermission(arg0);
// this is how to get the real userName (or rather the login name)
IDToken idToken = kp.getKeycloakSecurityContext().getIdToken();
logger.info("==========================");
String userPreferredName = tokenController.getUserPreferredName(idToken);
logger.info("Preferred Name " + userPreferredName);
logger.info("==");
logger.info("Name " + tokenController.getName(idToken));
logger.info("==");
logger.info("Gender " + tokenController.getGender(idToken));
logger.info("==");
logger.info("Family Name " + tokenController.getFamilyName(idToken));
logger.info("Middle Name " + tokenController.getMiddlename(idToken));
logger.info("Given Name " + tokenController.getGivenName(idToken));
logger.info("==");
logger.info("NickName " + tokenController.getNickname(idToken));
logger.info("==");
logger.info("Email " + tokenController.getEmail(idToken));
logger.info("Phone " + tokenController.getPhoneNumber(idToken));
logger.info("==");
logger.info("Issuer " + tokenController.getIssuer(idToken));
Set<String> roles = tokenController.getRoles(kp);
String allRoles = String.join(" ", roles);
logger.info("Roles " + allRoles);
logger.info("==========================");
logger.info("Logging out:" + userPreferredName);
}
request.logout();
logger.info("Logged out");
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Logged Out.", "Logged Out."));
} else {
logger.info("Not Logged in");
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Not Logged In.", "Not Logged In."));
}
logger.info("<logout");
return "/home?faces-redirect=true";
}
public void profile() throws IOException {
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
externalContext.redirect("http://localhost:8180/auth/realms/ThePlanetsParty/account");
}
public String getName() {
String name = null;
if (request.getUserPrincipal() != null) {
Principal principal = request.getUserPrincipal();
KeycloakPrincipal<KeycloakSecurityContext> kp = (KeycloakPrincipal<KeycloakSecurityContext>) principal;
IDToken idToken = kp.getKeycloakSecurityContext().getIdToken();
name = tokenController.getName(idToken);
}
return name;
}
public String getRole() {
String role = null;
StringBuffer roleBuffy = new StringBuffer();
if (request.getUserPrincipal() != null) {
Principal principal = request.getUserPrincipal();
KeycloakPrincipal<KeycloakSecurityContext> kp = (KeycloakPrincipal<KeycloakSecurityContext>) principal;
IDToken idToken = kp.getKeycloakSecurityContext().getIdToken();
Set<String> roles = tokenController.getRoles(kp);
if (!roles.isEmpty()) {
Iterator<String> iterator = roles.iterator();
roleBuffy.append(iterator.next());
if (iterator.hasNext()) {
roleBuffy.append(" +");
}
}
role = roleBuffy.toString();
}
return role;
}
public String getRoles() {
String role = null;
StringBuffer roleBuffy = new StringBuffer();
if (request.getUserPrincipal() != null) {
Principal principal = request.getUserPrincipal();
KeycloakPrincipal<KeycloakSecurityContext> kp = (KeycloakPrincipal<KeycloakSecurityContext>) principal;
IDToken idToken = kp.getKeycloakSecurityContext().getIdToken();
Set<String> roles = tokenController.getRoles(kp);
if (!roles.isEmpty()) {
Iterator<String> iterator = roles.iterator();
roleBuffy.append(iterator.next());
if (iterator.hasNext()) {
roleBuffy.append(", ");
roleBuffy.append(iterator.next());
}
}
role = roleBuffy.toString();
}
return role;
}
}
PF12+, Quarkus 3.2+ (CDI, JPA etc.), JSF Bridge (MyFaces 4.0.1)
Dont forget the classifier:
Code: Select all
...primefaces
<classifier>jakarta</classifier>
... theme
<classifier>jakarta</classifier>