OAuth2 framework implementation.
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>oauth2-client</artifactId>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung.oauth2</groupId>
|
||||
<artifactId>oauth2-framework-impl</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<httpPort>9180</httpPort>
|
||||
<httpsPort>9543</httpsPort>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>net.wasdev.wlp.maven.plugins</groupId>
|
||||
<artifactId>liberty-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package com.baeldung.oauth2.client;
|
||||
|
||||
import org.eclipse.microprofile.config.Config;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
@WebServlet(urlPatterns = "/authorize")
|
||||
public class AuthorizationCodeServlet extends HttpServlet {
|
||||
|
||||
@Inject
|
||||
private Config config;
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
//...
|
||||
request.getSession().removeAttribute("tokenResponse");
|
||||
String state = UUID.randomUUID().toString();
|
||||
request.getSession().setAttribute("CLIENT_LOCAL_STATE", state);
|
||||
|
||||
String authorizationUri = config.getValue("provider.authorizationUri", String.class);
|
||||
String clientId = config.getValue("client.clientId", String.class);
|
||||
String redirectUri = config.getValue("client.redirectUri", String.class);
|
||||
String scope = config.getValue("client.scope", String.class);
|
||||
|
||||
String authorizationLocation = authorizationUri + "?response_type=code"
|
||||
+ "&client_id=" + clientId
|
||||
+ "&redirect_uri=" + redirectUri
|
||||
+ "&scope=" + scope
|
||||
+ "&state=" + state;
|
||||
response.sendRedirect(authorizationLocation);
|
||||
}
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
package com.baeldung.oauth2.client;
|
||||
|
||||
import org.eclipse.microprofile.config.Config;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.json.JsonObject;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.ws.rs.client.Client;
|
||||
import javax.ws.rs.client.ClientBuilder;
|
||||
import javax.ws.rs.client.Entity;
|
||||
import javax.ws.rs.client.WebTarget;
|
||||
import javax.ws.rs.core.Form;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import java.io.IOException;
|
||||
import java.util.Base64;
|
||||
|
||||
@WebServlet(urlPatterns = "/callback")
|
||||
public class CallbackServlet extends HttpServlet {
|
||||
|
||||
@Inject
|
||||
private Config config;
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
|
||||
//Error:
|
||||
String error = request.getParameter("error");
|
||||
if (error != null) {
|
||||
request.setAttribute("error", error);
|
||||
dispatch("/", request, response);
|
||||
return;
|
||||
}
|
||||
String localState = (String) request.getSession().getAttribute("CLIENT_LOCAL_STATE");
|
||||
if (!localState.equals(request.getParameter("state"))) {
|
||||
request.setAttribute("error", "The state attribute doesn't match !!");
|
||||
dispatch("/", request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
String code = request.getParameter("code");
|
||||
|
||||
Client client = ClientBuilder.newClient();
|
||||
WebTarget target = client.target(config.getValue("provider.tokenUri", String.class));
|
||||
|
||||
Form form = new Form();
|
||||
form.param("grant_type", "authorization_code");
|
||||
form.param("code", code);
|
||||
form.param("redirect_uri", config.getValue("client.redirectUri", String.class));
|
||||
|
||||
JsonObject tokenResponse = target.request(MediaType.APPLICATION_JSON_TYPE)
|
||||
.header(HttpHeaders.AUTHORIZATION, getAuthorizationHeaderValue())
|
||||
.post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE), JsonObject.class);
|
||||
|
||||
request.getSession().setAttribute("tokenResponse", tokenResponse);
|
||||
dispatch("/", request, response);
|
||||
}
|
||||
|
||||
private void dispatch(String location, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
RequestDispatcher requestDispatcher = request.getRequestDispatcher(location);
|
||||
requestDispatcher.forward(request, response);
|
||||
}
|
||||
|
||||
private String getAuthorizationHeaderValue() {
|
||||
String clientId = config.getValue("client.clientId", String.class);
|
||||
String clientSecret = config.getValue("client.clientSecret", String.class);
|
||||
String token = clientId + ":" + clientSecret;
|
||||
String encodedString = Base64.getEncoder().encodeToString(token.getBytes());
|
||||
return "Basic " + encodedString;
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package com.baeldung.oauth2.client;
|
||||
|
||||
import org.eclipse.microprofile.config.Config;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.json.JsonObject;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.ws.rs.client.*;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
@WebServlet(urlPatterns = "/downstream")
|
||||
public class DownstreamCallServlet extends HttpServlet {
|
||||
|
||||
@Inject
|
||||
private Config config;
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
|
||||
resp.setContentType("text/html;charset=UTF-8");
|
||||
String action = request.getParameter("action");
|
||||
Client client = ClientBuilder.newClient();
|
||||
WebTarget webTarget = client.target(config.getValue("resourceServerUri", String.class));
|
||||
WebTarget resourceWebTarget;
|
||||
String response = null;
|
||||
JsonObject tokenResponse = (JsonObject) request.getSession().getAttribute("tokenResponse");
|
||||
if ("read".equals(action)) {
|
||||
resourceWebTarget = webTarget.path("resource/read");
|
||||
Invocation.Builder invocationBuilder = resourceWebTarget.request();
|
||||
response = invocationBuilder
|
||||
.header("authorization", tokenResponse.getString("access_token"))
|
||||
.get(String.class);
|
||||
} else if ("write".equals(action)) {
|
||||
resourceWebTarget = webTarget.path("resource/write");
|
||||
Invocation.Builder invocationBuilder = resourceWebTarget.request();
|
||||
response = invocationBuilder
|
||||
.header("authorization", tokenResponse.getString("access_token"))
|
||||
.post(Entity.text("body string"), String.class);
|
||||
}
|
||||
PrintWriter out = resp.getWriter();
|
||||
out.println(response);
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<server description="${project.artifactId}">
|
||||
|
||||
<featureManager>
|
||||
<feature>localConnector-1.0</feature>
|
||||
<feature>cdi-2.0</feature>
|
||||
<feature>jsp-2.3</feature>
|
||||
<feature>mpConfig-1.3</feature>
|
||||
<feature>jaxrsClient-2.1</feature>
|
||||
<feature>jsonp-1.1</feature>
|
||||
</featureManager>
|
||||
|
||||
<httpEndpoint id="defaultHttpEndpoint" httpPort="${httpPort}" httpsPort="${httpsPort}"/>
|
||||
|
||||
<applicationManager autoExpand="true"/>
|
||||
<applicationMonitor updateTrigger="mbean"/>
|
||||
<application type="war" location="${project.build.finalName}.war" context-root="/"/>
|
||||
|
||||
</server>
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
#Client registration
|
||||
client.clientId=webappclient
|
||||
client.clientSecret=webappclientsecret
|
||||
client.redirectUri=http://localhost:9180/callback
|
||||
client.scope=resource.read resource.write
|
||||
|
||||
#Provider
|
||||
provider.authorizationUri=http://127.0.0.1:9080/authorize
|
||||
provider.tokenUri=http://127.0.0.1:9080/token
|
||||
|
||||
#Resource Server
|
||||
resourceServerUri=http://localhost:9280/api
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
|
||||
bean-discovery-mode="all">
|
||||
</beans>
|
||||
@@ -0,0 +1,5 @@
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="3.0">
|
||||
<welcome-file-list>
|
||||
<welcome-file>index.jsp</welcome-file>
|
||||
</welcome-file-list>
|
||||
</web-app>
|
||||
@@ -0,0 +1,97 @@
|
||||
<%@ page import="org.eclipse.microprofile.config.Config" %>
|
||||
<%@ page import="org.eclipse.microprofile.config.ConfigProvider" %>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>OAuth2 Client</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0px;
|
||||
}
|
||||
input[type=text], input[type=password] {
|
||||
width: 75%;
|
||||
padding: 4px 0px;
|
||||
display: inline-block;
|
||||
border: 1px solid #502bcc;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.container-error {
|
||||
padding: 16px;
|
||||
border: 1px solid #cc102a;
|
||||
background: #f50307;
|
||||
width: 75%;
|
||||
margin-left: 25px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
.container {
|
||||
padding: 16px;
|
||||
border: 1px solid #130ecc;
|
||||
background: #eaecf5;
|
||||
width: 75%;
|
||||
margin-left: 25px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<%
|
||||
Config config1 = ConfigProvider.getConfig();
|
||||
%>
|
||||
|
||||
<div class="container-error" style="visibility: <%=request.getAttribute("error")!=null?"visible":"hidden"%>">
|
||||
<span>Error : ${error}</span>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<span><h4>OAuth2 Authorization Server</h4></span>
|
||||
<hr>
|
||||
<p>Client Registration :</p>
|
||||
<ul>
|
||||
<li>client_id: <%=config1.getValue("client.clientId", String.class)%>
|
||||
</li>
|
||||
<li>client_secret: <%=config1.getValue("client.clientSecret", String.class)%>
|
||||
</li>
|
||||
<li>redirect_uri: <%=config1.getValue("client.redirectUri", String.class)%>
|
||||
</li>
|
||||
<li>scope: <%=config1.getValue("client.scope", String.class)%>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Authorization Server :</p>
|
||||
<ul>
|
||||
<li>authorization_uri: <%=config1.getValue("provider.authorizationUri", String.class)%>
|
||||
</li>
|
||||
<li>token_uri: <%=config1.getValue("provider.tokenUri", String.class)%>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="container">
|
||||
<span><h4>OAuth2 Client</h4></span>
|
||||
<hr>
|
||||
<p>Token Request :</p>
|
||||
<ul>
|
||||
<li><a class="btn btn-primary" href="/authorize">Get Access Token</a></li>
|
||||
</ul>
|
||||
|
||||
<p>Token Response:</p>
|
||||
<ul>
|
||||
<li>access_token: ${tokenResponse.getString("access_token")}</li>
|
||||
<li>scope: ${tokenResponse.getString("scope")}</li>
|
||||
<li>Expires in (s): ${tokenResponse.getInt("expires_in")}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="container">
|
||||
<span><h4>OAuth2 Resource Server Call</h4></span>
|
||||
<hr>
|
||||
<ul>
|
||||
<li><a href="downstream?action=read">Read Protected Resource</a></li>
|
||||
<li><a href="downstream?action=write">Write Protected Resource</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user