Skip to content

Commit 70acdad

Browse files
authored
SDK Basic Usage. HTTP headers. (#10)
1 parent a931453 commit 70acdad

7 files changed

Lines changed: 128 additions & 48 deletions

File tree

publisher/uid2-java-test-site/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Java UID2 Integration Example
22

3-
This example demonstrates how a content publisher can use the [UID2 services](https://github.com/UnifiedID2/uid2docs/tree/main) to implement the [custom UID2 integration workflow](https://github.com/UnifiedID2/uid2docs/blob/main/api/v2/guides/custom-publisher-integration.md).
3+
This example demonstrates how a content publisher can use the [UID2 Java SDK](https://github.com/IABTechLab/uid2-client-java) to implement [UID2 Publisher integrations](https://github.com/UnifiedID2/uid2docs/blob/main/api/v2/guides/README.md).
44

55

66
>NOTE: While the server side of this example application is implemented in Java using Vert.x, it is not a requirement. You can use any technology of your choice and refer to the example application for illustration of the functionality that needs to be implemented.

publisher/uid2-java-test-site/src/main/java/com/uid2/testsite/MainVerticle.java

Lines changed: 121 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ private void render(RoutingContext ctx, String templateFileName, JsonObject json
3636
private static final String UID2_BASE_URL = System.getenv("UID2_BASE_URL");
3737
private static final String UID2_API_KEY = System.getenv("UID2_API_KEY");
3838
private static final String UID2_SECRET_KEY = System.getenv("UID2_SECRET_KEY");
39-
private final PublisherUid2Helper publisherUid2Helper = new PublisherUid2Helper(UID2_SECRET_KEY);
39+
private final PublisherUid2Helper publisherUid2Helper = new PublisherUid2Helper(UID2_SECRET_KEY); //for advanced usage (Do your own HTTP)
40+
private final PublisherUid2Client publisherUid2Client = new PublisherUid2Client(UID2_BASE_URL, UID2_API_KEY, UID2_SECRET_KEY); //for basic usage (SDK does HTTP)
4041

4142

4243
private int GetPort() {
@@ -61,13 +62,26 @@ private void renderError(HttpResponse<Buffer> response, String errorMessage, Rou
6162

6263
private WebClient webClient;
6364

64-
private void generateToken(RoutingContext ctx, String email, String redirect) {
65+
private void generateTokenBasicUsage(RoutingContext ctx, String email) {
66+
try {
67+
IdentityTokens identity = publisherUid2Client.generateToken(TokenGenerateInput.fromEmail(email));
68+
69+
setIdentity(ctx, identity.getJsonString());
70+
ctx.redirect("/basic/");
71+
} catch (RuntimeException e) {
72+
renderError(null, e.getMessage(), ctx);
73+
}
74+
}
75+
76+
77+
private void generateTokenAdvancedUsage(RoutingContext ctx, String email, String redirect) {
6578
try {
6679
EnvelopeV2 envelope = publisherUid2Helper.createEnvelopeForTokenGenerateRequest(TokenGenerateInput.fromEmail(email));
6780

6881
webClient
6982
.postAbs(UID2_BASE_URL + "/v2/token/generate")
7083
.putHeader("Authorization", "Bearer " + UID2_API_KEY)
84+
.putHeader("X-UID2-Client-Version", PublisherUid2Helper.getVersionHttpHeader())
7185
.sendBuffer(Buffer.buffer(envelope.getEnvelope()))
7286
.onSuccess(response -> {
7387
if (response.statusCode() != 200) {
@@ -121,33 +135,50 @@ private void processRefreshIdentityResponse(HttpResponse<Buffer> encryptedRespon
121135
}
122136
}
123137

124-
private Future<Void> refreshIdentity(RoutingContext ctx) {
138+
private Future<Void> refreshIdentity(RoutingContext ctx, boolean basicUsage) {
125139
Promise<Void> promise = Promise.promise();
126140

127141
final IdentityTokens identity = getIdentity(ctx);
128-
String refreshToken = identity.getRefreshToken();
129-
130-
webClient
131-
.postAbs(UID2_BASE_URL + "/v2/token/refresh")
132-
.putHeader("Authorization", "Bearer " + UID2_API_KEY)
133-
.sendBuffer(Buffer.buffer(refreshToken))
134-
.onSuccess(encryptedResponse -> {
135-
processRefreshIdentityResponse(encryptedResponse, ctx, identity);
136-
if (getIdentity(ctx) == null)
142+
143+
if (basicUsage) {
144+
try {
145+
TokenRefreshResponse tokenRefreshResponse = publisherUid2Client.refreshToken(identity);
146+
String identityJsonString = tokenRefreshResponse.getIdentityJsonString();
147+
setIdentity(ctx, identityJsonString);
148+
149+
if (identityJsonString == null)
137150
promise.fail("no identity"); //eg opt out
138151
else
139152
promise.complete();
140-
})
141-
.onFailure(err -> {
142-
renderError(null, err.getMessage(), ctx);
143-
promise.fail("something went wrong" + err.getMessage());
144-
});
153+
} catch (RuntimeException e) {
154+
renderError(null, e.getMessage(), ctx);
155+
}
156+
} else { //advanced usage
157+
String refreshToken = identity.getRefreshToken();
158+
159+
webClient
160+
.postAbs(UID2_BASE_URL + "/v2/token/refresh")
161+
.putHeader("Authorization", "Bearer " + UID2_API_KEY)
162+
.putHeader("X-UID2-Client-Version", PublisherUid2Helper.getVersionHttpHeader())
163+
.sendBuffer(Buffer.buffer(refreshToken))
164+
.onSuccess(encryptedResponse -> {
165+
processRefreshIdentityResponse(encryptedResponse, ctx, identity);
166+
if (getIdentity(ctx) == null)
167+
promise.fail("no identity"); //eg opt out
168+
else
169+
promise.complete();
170+
})
171+
.onFailure(err -> {
172+
renderError(null, err.getMessage(), ctx);
173+
promise.fail("something went wrong" + err.getMessage());
174+
});
175+
}
145176

146177
return promise.future();
147178
}
148179

149180

150-
private Future<Void> verifyIdentity(RoutingContext ctx) {
181+
private Future<Void> verifyIdentity(RoutingContext ctx, boolean basicUsage) {
151182
Promise<Void> promise = Promise.promise();
152183

153184
IdentityTokens identity = getIdentity(ctx);
@@ -157,7 +188,7 @@ private Future<Void> verifyIdentity(RoutingContext ctx) {
157188
}
158189

159190
if (identity.isDueForRefresh()) {
160-
return refreshIdentity(ctx);
191+
return refreshIdentity(ctx, basicUsage);
161192
}
162193

163194
if (getIdentity(ctx) != null)
@@ -168,96 +199,145 @@ private Future<Void> verifyIdentity(RoutingContext ctx) {
168199
return promise.future();
169200
}
170201

171-
void protect(RoutingContext ctx) {
172-
verifyIdentity(ctx)
202+
void protect(RoutingContext ctx, boolean basicUsage) {
203+
final String redirect = basicUsage ? "/basic/login" : "/login";
204+
205+
verifyIdentity(ctx, basicUsage)
173206
.onSuccess(v -> ctx.next())
174207
.onFailure(err -> {
175208
setIdentity(ctx, null);
176-
ctx.redirect("/login");
209+
ctx.redirect(redirect);
177210
});
178211
}
179212

180-
private JsonObject getIdentityForTemplate(RoutingContext ctx) {
213+
private JsonObject getIdentityForTemplate(RoutingContext ctx, String prefix) {
181214
IdentityTokens identity = getIdentity(ctx);
182-
return new JsonObject().put("identity", new JsonObject(identity.getJsonString()).encodePrettily());
215+
return new JsonObject().put("prefix", prefix).put("identity", new JsonObject(identity.getJsonString()).encodePrettily());
183216
}
184217

185218
private TemplateEngine engine;
186219

187-
private Router createRoutesSetupForServerOnlyIntegration() {
188-
engine = FreeMarkerTemplateEngine.create(vertx);
220+
private Router createRoutesSetupForAdvancedUsageServerOnly() {
189221
final Router router = Router.router(vertx);
190222

191223
router.route().handler(BodyHandler.create());
192224
router.route().handler(SessionHandler.create(CookieSessionStore.create(vertx, "my-secret")));
193225
router.route().handler(StaticHandler.create("webroot"));
194226

195227
router.get("/login").handler(ctx ->
196-
verifyIdentity(ctx)
228+
verifyIdentity(ctx, false)
197229
.onSuccess(v -> ctx.redirect("/"))
198230
.onFailure(v -> {
199231
setIdentity(ctx, null);
200-
render(ctx, "templates/login.ftl", new JsonObject());
232+
render(ctx, "templates/login.ftl", new JsonObject().put("redirect", "/login"));
201233
})
202234
);
203235

204236
router.post("/login").handler(ctx ->
205-
generateToken(ctx, ctx.request().getFormAttribute("email"), "/")
237+
generateTokenAdvancedUsage(ctx, ctx.request().getFormAttribute("email"), "/")
206238
);
207239

208240
router.get("/logout").handler(ctx -> {
209241
setIdentity(ctx, null);
210242
ctx.redirect("/login");
211243
});
212244

213-
router.get("/").handler(this::protect);
214-
router.get("/content1").handler(this::protect);
215-
router.get("/content2").handler(this::protect);
245+
router.get("/").handler(ctx -> protect(ctx, false));
246+
router.get("/content1").handler(ctx -> protect(ctx, false));
247+
router.get("/content2").handler(ctx -> protect(ctx, false));
216248

217249
router.get("/").handler(ctx -> {
218-
JsonObject jsonObject = getIdentityForTemplate(ctx);
250+
JsonObject jsonObject = getIdentityForTemplate(ctx, "");
219251
render(ctx, "templates/index.ftl", jsonObject);
220252
});
221253

222254
router.get("/content1").handler(ctx -> {
223-
JsonObject jsonObject = getIdentityForTemplate(ctx).put("content", "First Sample Content");
255+
JsonObject jsonObject = getIdentityForTemplate(ctx, "").put("content", "First Sample Content");
224256
render(ctx, "templates/content.ftl", jsonObject);
225257
});
226258

227259
router.get("/content2").handler(ctx -> {
228-
JsonObject jsonObject = getIdentityForTemplate(ctx).put("content", "Second Sample Content");
260+
JsonObject jsonObject = getIdentityForTemplate(ctx, "").put("content", "Second Sample Content");
229261
render(ctx, "templates/content.ftl", jsonObject);
230262
});
231263

232264
return router;
233265
}
234266

235-
private Router createRoutesSetupForStandardIntegration() {
267+
private Router createRoutesSetupForAdvancedUsageStandardIntegration() {
236268
Router standardIntegration = Router.router(vertx);
237269

238270
standardIntegration.get("/").handler(ctx ->
239271
render(ctx, "templates-standard-integration/index.ftl", new JsonObject().put("uid2BaseUrl", UID2_BASE_URL)));
240272

241273
standardIntegration.post("/login").handler(ctx ->
242-
generateToken(ctx, ctx.request().getFormAttribute("email"), "/standard/login"));
274+
generateTokenAdvancedUsage(ctx, ctx.request().getFormAttribute("email"), "/standard/login"));
243275

244276
standardIntegration.get("/login").handler(ctx ->
245-
render(ctx, "templates-standard-integration/login.ftl", getIdentityForTemplate(ctx).put("uid2BaseUrl", UID2_BASE_URL)));
277+
render(ctx, "templates-standard-integration/login.ftl", getIdentityForTemplate(ctx, "/standard").put("uid2BaseUrl", UID2_BASE_URL)));
246278

247279
return standardIntegration;
248280
}
249281

282+
private Router createRouteSetupForBasicUsageServerOnly() {
283+
final Router router = Router.router(vertx);
284+
285+
router.route().handler(BodyHandler.create());
286+
router.route().handler(SessionHandler.create(CookieSessionStore.create(vertx, "my-secret")));
287+
router.route().handler(StaticHandler.create("webroot"));
288+
289+
router.get("/login").handler(ctx ->
290+
verifyIdentity(ctx, true)
291+
.onSuccess(v -> ctx.redirect("/"))
292+
.onFailure(v -> {
293+
setIdentity(ctx, null);
294+
render(ctx, "templates/login.ftl", new JsonObject().put("redirect", "/basic/login"));
295+
})
296+
);
297+
298+
router.post("/login").handler(ctx -> generateTokenBasicUsage(ctx, ctx.request().getFormAttribute("email")));
299+
300+
router.get("/logout").handler(ctx -> {
301+
setIdentity(ctx, null);
302+
ctx.redirect("/basic/login");
303+
});
304+
305+
router.get("/").handler(ctx -> protect(ctx, true));
306+
router.get("/content1").handler(ctx -> protect(ctx, true));
307+
router.get("/content2").handler(ctx -> protect(ctx, true));
308+
309+
router.get("/").handler(ctx -> {
310+
JsonObject jsonObject = getIdentityForTemplate(ctx, "/basic");
311+
render(ctx, "templates/index.ftl", jsonObject);
312+
});
313+
314+
router.get("/content1").handler(ctx -> {
315+
JsonObject jsonObject = getIdentityForTemplate(ctx, "/basic").put("content", "First Sample Content");
316+
render(ctx, "templates/content.ftl", jsonObject);
317+
});
318+
319+
router.get("/content2").handler(ctx -> {
320+
JsonObject jsonObject = getIdentityForTemplate(ctx, "/basic").put("content", "Second Sample Content");
321+
render(ctx, "templates/content.ftl", jsonObject);
322+
});
323+
324+
return router;
325+
326+
}
327+
250328
@Override
251329
public void start(Promise<Void> startPromise) {
252330
webClient = WebClient.create(vertx);
331+
engine = FreeMarkerTemplateEngine.create(vertx);
253332

254-
Router serverOnlyRouter = createRoutesSetupForServerOnlyIntegration();
255-
Router standardIntegrationRouter = createRoutesSetupForStandardIntegration();
333+
Router serverOnlyRouter = createRoutesSetupForAdvancedUsageServerOnly();
334+
Router standardIntegrationRouter = createRoutesSetupForAdvancedUsageStandardIntegration();
335+
Router serverOnlyWithBasicUsage = createRouteSetupForBasicUsageServerOnly();
256336

257337
Router parentRouter = Router.router(vertx);
258338
parentRouter.route("/*").subRouter(serverOnlyRouter);
259339
parentRouter.route("/standard/*").subRouter(standardIntegrationRouter);
260-
340+
parentRouter.route("/basic/*").subRouter(serverOnlyWithBasicUsage);
261341

262342
vertx.createHttpServer().requestHandler(parentRouter).listen(GetPort())
263343
.onSuccess(server -> System.out.println("HTTP server started on http://localhost:" + server.actualPort()))
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<#include "header.html">
22
<p>Protected Content &mdash; accessible only with a valid UID2 identity:</p>
33
<pre>${content}</pre>
4-
<p><a href="/">Back to the main page</a></p>
4+
<p><a href="${prefix}/">Back to the main page</a></p>
55
<#include "identity.ftl">
66
<#include "footer.html">

publisher/uid2-java-test-site/templates/error.ftl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
<pre>${response}</pre>
66
<p>HTTP error:</p>
77
<pre>${responseStatus}</pre>
8-
<p><a href="/">Back to the main page</a></p>
8+
<p><a href="${prefix}/">Back to the main page</a></p>
99
<#include "footer.html">
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
<pre>${identity}</pre>
2-
<div id="logout_form" class="form"><form action="/logout" method="GET">
2+
<div id="logout_form" class="form"><form action="${prefix}/logout" method="GET">
33
<input type="submit" value="Log Out" class="button">
44
</form></div>

publisher/uid2-java-test-site/templates/index.ftl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<#include "header.html">
22
<p>Protected Content &mdash; accessible only with a valid UID2 identity:</p>
33
<ul>
4-
<li><a href="/content1">Sample Page 1</a></li>
5-
<li><a href="/content2">Sample Page 2</a></li>
4+
<li><a href="${prefix}/content1">Sample Page 1</a></li>
5+
<li><a href="${prefix}/content2">Sample Page 2</a></li>
66
</ul>
77
<p>Current UID2 Identity:</p>
88
<#include "identity.ftl">

publisher/uid2-java-test-site/templates/login.ftl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<#include "header.html">
2-
<div id="login_form" class="form"><form action="/login" method="POST">
2+
<div id="login_form" class="form"><form action="${redirect}" method="POST">
33
<div class="email_prompt"><input type="text" id="email" name="email" placeholder="Enter an email address" style="border-style: none;"></div>
44
<div><input type="submit" value="Log In" class="button"></div>
55
</form></div>

0 commit comments

Comments
 (0)