I have the requirement to protect my existing Jakarta EE application with an OpenID provider in one of many different environments.
When searching about this topic you will find the @OpenIdAuthenticationDefinition defined by Payara and explained in this blog and also the new annotation @OpenIdAuthenticationMechanismDefinition introduced in Jakrata EE10.
@OpenIdAuthenticationDefinition(
providerURI = "https://sample-openid-server.com",
clientId = "...",
clientSecret = "...",
redirectURI = "${baseURL}/callback",
...)
public class MySecureBean {
}
But I did not understand the concept behind it. I know OpenID, it is the annotation which confuses me. So my first question is:
Does the @OpenIdAuthenticationDefinition mean that I have to annotate each of my CDI and EJB code using the JakaraEE security API? This would mean I have to rewrite many classes and third party libraries in my application?
The second question is more a conceptional about the design of my application:
Why should I pollute my code with an annotation that binds my code to a specific proprietary security layer? It is one of the core concepts of Jakrata EE to write application code against the specification and not one specific implementation. For example you implement your data layer against JPA and not against a concrete Database Vendor like Oracle or PostgreSQL. This is true for all the other cross functions aspects like directory lookups, messaging or even the security.
So the annotation looks to me like one step forward and two steps back. Or did I miss something?
On the other hand, if it is sufficient to use the @OpenIdAuthenticationDefinition annotation just in one application scoped CDI bean to propagate the user credentials to all other components in my application and libraries using the security API, why is there not a general open source implementation of such a OpenID library?
In a JSF application, just define the access to the OpenID Provider :
@OpenIdAuthenticationMechanismDefinition(
clientId = "${oidConfig.clientId}"
, clientSecret = "${oidConfig.clientSecret}"
, redirectURI = "${baseURL}/Callback"
, providerURI = "${oidConfig.providerURI}"
, logout = @LogoutDefinition(redirectURI = "${baseURL}/index.xhtml")
)
@Named("oidConfig")
@ApplicationScoped
@SuppressWarnings("serial")
public class OpenIdConfiguration implements Serializable {
@Inject
@ConfigProperty(name = "clientId")
private String clientId;
@Inject
@ConfigProperty(name = "clientSecret")
private String clientSecret;
@Inject
@ConfigProperty(name = "providerURI")
private String providerURI;
}
The callback which redirects to the original resource:
@WebServlet("/Callback")
public class CallbackServlet extends HttpServlet {
@Inject
private OpenIdContext context;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (context != null) {
Optional<String> opt = context.getStoredValue(request, response, OpenIdConstant.ORIGINAL_REQUEST);
String redirect = opt.orElse("");
response.sendRedirect(redirect);
}
}
}
In your web.xml add security constraint as usual :
<security-constraint>
<web-resource-collection>
<web-resource-name>Admin pages</web-resource-name>
<url-pattern>/admin/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
</security-role>
You might need to add a group IdentityStore
@ApplicationScoped
public class MyGroupsIdentityStore implements IdentityStore {
@Override
public Set<String> getCallerGroups(CredentialValidationResult validationResult) {
//TODO
}
@Override
public Set<ValidationType> validationTypes() {
return Collections.singleton(PROVIDE_GROUPS);
}
}
This will do with "container-initiated authentication".
For the "caller-initiated authentication" (with "login" button") you can use this bean
@Named
@RequestScoped
public class LoginView {
@Inject
private SecurityContext securityContext;
public void login() {
securityContext.authenticate(getRequest(), getResponse()
, new AuthenticationParameters()
);
}
}
A good video you might want to watch : https://www.youtube.com/watch?v=IEt35RZqsN4
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With