Skip to content

Commit dd76ab6

Browse files
committed
oauth2 example is now polyglot
1 parent 3fed412 commit dd76ab6

File tree

14 files changed

+545
-86
lines changed

14 files changed

+545
-86
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import groovy.transform.Field
2+
import io.vertx.ext.web.Router
3+
import io.vertx.ext.web.handler.CookieHandler
4+
import io.vertx.ext.web.sstore.LocalSessionStore
5+
import io.vertx.ext.web.handler.SessionHandler
6+
import io.vertx.ext.auth.oauth2.providers.GithubAuth
7+
import io.vertx.ext.web.handler.UserSessionHandler
8+
import io.vertx.ext.web.handler.OAuth2AuthHandler
9+
import io.vertx.ext.auth.oauth2.AccessToken
10+
import io.vertx.ext.web.templ.HandlebarsTemplateEngine
11+
@Field def CLIENT_SECRET = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
12+
@Field def CLIENT_ID = "xxxxxxxxxxxxxxxxxxxx"
13+
@Field def engine = HandlebarsTemplateEngine.create()
14+
// To simplify the development of the web components we use a Router to route all HTTP requests
15+
// to organize our code in a reusable way.
16+
def router = Router.router(vertx)
17+
// We need cookies and sessions
18+
router.route().handler(CookieHandler.create())
19+
router.route().handler(SessionHandler.create(LocalSessionStore.create(vertx)))
20+
// Simple auth service which uses a GitHub to authenticate the user
21+
def authProvider = GithubAuth.create(vertx, CLIENT_ID, CLIENT_SECRET)
22+
// We need a user session handler too to make sure the user is stored in the session between requests
23+
router.route().handler(UserSessionHandler.create(authProvider))
24+
// we now protect the resource under the path "/protected"
25+
router.route("/protected").handler(OAuth2AuthHandler.create(authProvider).setupCallback(router.route("/callback")).addAuthority("user:email"))
26+
// Entry point to the application, this will render a custom template.
27+
router.get("/").handler({ ctx ->
28+
// we pass the client id to the template
29+
ctx.put("client_id", CLIENT_ID)
30+
// and now delegate to the engine to render it.
31+
engine.render(ctx, "views", "/index.hbs", { res ->
32+
if (res.succeeded()) {
33+
ctx.response().putHeader("Content-Type", "text/html").end(res.result())
34+
} else {
35+
ctx.fail(res.cause())
36+
}
37+
})
38+
})
39+
// The protected resource
40+
router.get("/protected").handler({ ctx ->
41+
def user = ctx.user()
42+
43+
user.userInfo({ res ->
44+
if (res.failed()) {
45+
// request didn't succeed because the token was revoked so we
46+
// invalidate the token stored in the session and render the
47+
// index page so that the user can start the OAuth flow again
48+
ctx.session().destroy()
49+
ctx.fail(res.cause())
50+
} else {
51+
// the request succeeded, so we use the API to fetch the user's emails
52+
def userInfo = res.result()
53+
54+
// fetch the user emails from the github API
55+
user.fetch("https://api.github.com/user/emails", { res2 ->
56+
if (res2.failed()) {
57+
// request didn't succeed because the token was revoked so we
58+
// invalidate the token stored in the session and render the
59+
// index page so that the user can start the OAuth flow again
60+
ctx.session().destroy()
61+
ctx.fail(res2.cause())
62+
} else {
63+
userInfo.private_emails = res2.result().jsonArray()
64+
// we pass the client info to the template
65+
ctx.put("userInfo", userInfo)
66+
// and now delegate to the engine to render it.
67+
engine.render(ctx, "views", "/advanced.hbs", { res3 ->
68+
if (res3.succeeded()) {
69+
ctx.response().putHeader("Content-Type", "text/html").end(res3.result())
70+
} else {
71+
ctx.fail(res3.cause())
72+
}
73+
})
74+
}
75+
})
76+
}
77+
})
78+
})
79+
80+
vertx.createHttpServer().requestHandler(router.&accept).listen(8080)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<html>
2+
<head>
3+
</head>
4+
<body>
5+
<p>Well, well, well, {{userInfo.login}}!</p>
6+
<p>
7+
{{#if userInfo.email}} It looks like your public email address is {{userInfo.email}}.
8+
{{else}} It looks like you don't have a public email. That's cool.
9+
{{/if}}
10+
</p>
11+
<p>
12+
{{#if userInfo.private_emails}}
13+
With your permission, we were also able to dig up your private email addresses:
14+
{{#each userInfo.private_emails}}
15+
{{email}},
16+
{{/each}}
17+
{{else}}
18+
Also, you're a bit secretive about your private email addresses.
19+
{{/if}}
20+
</p>
21+
</body>
22+
</html>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<html>
2+
<head>
3+
</head>
4+
<body>
5+
<p>
6+
Well, hello there!
7+
</p>
8+
<p>
9+
We're going to the protected resource, if there is no user in the session we will talk to the GitHub API. Ready?
10+
<a href="/protected">Click here</a> to begin!</a>
11+
</p>
12+
<p>
13+
<b>If that link doesn't work</b>, remember to provide your own <a href="https://github.com/settings/applications/new">Client ID</a>!
14+
</p>
15+
</body>
16+
</html>

web-examples/src/main/java/io/vertx/example/web/oauth2/Server.java

Lines changed: 66 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import io.vertx.ext.auth.oauth2.OAuth2Auth;
99
import io.vertx.ext.auth.oauth2.providers.GithubAuth;
1010
import io.vertx.ext.web.Router;
11-
import io.vertx.ext.web.RoutingContext;
1211
import io.vertx.ext.web.handler.*;
1312
import io.vertx.ext.web.sstore.LocalSessionStore;
1413
import io.vertx.ext.web.templ.HandlebarsTemplateEngine;
@@ -18,114 +17,98 @@
1817
*/
1918
public class Server extends AbstractVerticle {
2019

21-
private static final String CLIENT_ID = System.getenv("GH_BASIC_CLIENT_ID");
22-
private static final String CLIENT_SECRET = System.getenv("GH_BASIC_SECRET_ID");
23-
24-
// In order to use a template we first need to create an engine
25-
private final HandlebarsTemplateEngine engine = HandlebarsTemplateEngine.create();
26-
2720
// Convenience method so you can run it in your IDE
2821
public static void main(String[] args) {
2922
Runner.runExample(Server.class);
3023
}
3124

32-
private boolean isAuthenticated(RoutingContext ctx) {
33-
return ctx.user() != null;
34-
}
25+
// you should never store these in code,
26+
// these are your github application credentials
27+
private static final String CLIENT_ID = "xxxxxxxxxxxxxxxxxxxx";
28+
private static final String CLIENT_SECRET = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
3529

36-
private void authenticate(RoutingContext ctx) {
37-
// we pass the client id to the template
38-
ctx.put("client_id", CLIENT_ID);
39-
// and now delegate to the engine to render it.
40-
engine.render(ctx, "views", "/index.hbs", res -> {
41-
if (res.succeeded()) {
42-
ctx.response()
43-
.putHeader("Content-Type", "text/html")
44-
.end(res.result());
45-
} else {
46-
ctx.fail(res.cause());
47-
}
48-
});
49-
}
30+
// In order to use a template we first need to create an engine
31+
private final HandlebarsTemplateEngine engine = HandlebarsTemplateEngine.create();
5032

5133
@Override
5234
public void start() throws Exception {
5335
// To simplify the development of the web components we use a Router to route all HTTP requests
5436
// to organize our code in a reusable way.
5537
final Router router = Router.router(vertx);
56-
// We need cookies, sessions and request bodies
38+
// We need cookies and sessions
5739
router.route().handler(CookieHandler.create());
58-
router.route().handler(BodyHandler.create());
5940
router.route().handler(SessionHandler.create(LocalSessionStore.create(vertx)));
6041
// Simple auth service which uses a GitHub to authenticate the user
6142
OAuth2Auth authProvider = GithubAuth.create(vertx, CLIENT_ID, CLIENT_SECRET);
6243
// We need a user session handler too to make sure the user is stored in the session between requests
6344
router.route().handler(UserSessionHandler.create(authProvider));
45+
// we now protect the resource under the path "/protected"
46+
router.route("/protected").handler(
47+
OAuth2AuthHandler.create(authProvider)
48+
// we now configure the oauth2 handler, it will setup the callback handler
49+
// as expected by your oauth2 provider.
50+
.setupCallback(router.route("/callback"))
51+
// for this resource we require that users have the authority to retrieve the user emails
52+
.addAuthority("user:email")
53+
);
6454
// Entry point to the application, this will render a custom template.
6555
router.get("/").handler(ctx -> {
66-
if (!isAuthenticated(ctx)) {
67-
authenticate(ctx);
68-
} else {
69-
AccessToken user = (AccessToken) ctx.user();
70-
71-
user.userInfo(res -> {
72-
if (res.failed()) {
73-
res.cause().printStackTrace();
74-
// request didn't succeed because the token was revoked so we
75-
// invalidate the token stored in the session and render the
76-
// index page so that the user can start the OAuth flow again
77-
ctx.session().destroy();
78-
authenticate(ctx);
79-
} else {
80-
// the request succeeded, so we check the list of current scopes
81-
JsonArray scopes = new JsonArray();
82-
JsonObject userInfo = res.result();
83-
84-
if (userInfo.containsKey("X-OAuth-Scopes")) {
85-
for (String scope : userInfo.getString("X-OAuth-Scopes").split(", ")) {
86-
scopes.add(scope);
87-
}
88-
}
89-
90-
if (scopes.contains("user:email")) {
91-
// fetch the user emails from the github API
92-
user.fetch("https://api.github.com/user/emails", res2 -> {
93-
if (res2.failed()) {
94-
res2.cause().printStackTrace();
95-
// request didn't succeed because the token was revoked so we
96-
// invalidate the token stored in the session and render the
97-
// index page so that the user can start the OAuth flow again
98-
ctx.session().destroy();
99-
authenticate(ctx);
56+
// we pass the client id to the template
57+
ctx.put("client_id", CLIENT_ID);
58+
// and now delegate to the engine to render it.
59+
engine.render(ctx, "views", "/index.hbs", res -> {
60+
if (res.succeeded()) {
61+
ctx.response()
62+
.putHeader("Content-Type", "text/html")
63+
.end(res.result());
64+
} else {
65+
ctx.fail(res.cause());
66+
}
67+
});
68+
});
69+
// The protected resource
70+
router.get("/protected").handler(ctx -> {
71+
AccessToken user = (AccessToken) ctx.user();
72+
73+
user.userInfo(res -> {
74+
if (res.failed()) {
75+
// request didn't succeed because the token was revoked so we
76+
// invalidate the token stored in the session and render the
77+
// index page so that the user can start the OAuth flow again
78+
ctx.session().destroy();
79+
ctx.fail(res.cause());
80+
} else {
81+
// the request succeeded, so we use the API to fetch the user's emails
82+
final JsonObject userInfo = res.result();
83+
84+
// fetch the user emails from the github API
85+
user.fetch("https://api.github.com/user/emails", res2 -> {
86+
if (res2.failed()) {
87+
// request didn't succeed because the token was revoked so we
88+
// invalidate the token stored in the session and render the
89+
// index page so that the user can start the OAuth flow again
90+
ctx.session().destroy();
91+
ctx.fail(res2.cause());
92+
} else {
93+
userInfo.put("private_emails", res2.result().jsonArray());
94+
// we pass the client info to the template
95+
ctx.put("userInfo", userInfo);
96+
// and now delegate to the engine to render it.
97+
engine.render(ctx, "views", "/advanced.hbs", res3 -> {
98+
if (res3.succeeded()) {
99+
ctx.response()
100+
.putHeader("Content-Type", "text/html")
101+
.end(res3.result());
100102
} else {
101-
userInfo.put("private_emails", res2.result().jsonArray());
102-
103-
// we pass the client id to the template
104-
ctx.put("userInfo", userInfo);
105-
106-
// and now delegate to the engine to render it.
107-
engine.render(ctx, "views", "/advanced.hbs", res3 -> {
108-
if (res3.succeeded()) {
109-
ctx.response()
110-
.putHeader("Content-Type", "text/html")
111-
.end(res3.result());
112-
} else {
113-
ctx.fail(res3.cause());
114-
}
115-
});
103+
ctx.fail(res3.cause());
116104
}
117105
});
118106
}
119-
120-
}
121-
});
122-
}
107+
});
108+
}
109+
});
123110
});
124-
// the callback url
125-
OAuth2AuthHandler oauth2Handler = OAuth2AuthHandler.create(authProvider, "http://localhost:8080/callback");
126-
oauth2Handler.setupCallback(router.route("/callback"));
127111

128112
vertx.createHttpServer().requestHandler(router::accept).listen(8080);
129113
}
130114
}
131-

web-examples/src/main/java/io/vertx/example/web/oauth2/views/index.hbs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
Well, hello there!
77
</p>
88
<p>
9-
We're going to now talk to the GitHub API. Ready?
10-
<a href="https://github.com/login/oauth/authorize?scope=user:email&client_id={{client_id}}">Click here</a> to begin!</a>
9+
We're going to the protected resource, if there is no user in the session we will talk to the GitHub API. Ready?
10+
<a href="/protected">Click here</a> to begin!</a>
1111
</p>
1212
<p>
13-
If that link doesn't work, remember to provide your own <a href="https://github.com/settings/applications/new">Client ID</a>!
13+
<b>If that link doesn't work</b>, remember to provide your own <a href="https://github.com/settings/applications/new">Client ID</a>!
1414
</p>
1515
</body>
1616
</html>

0 commit comments

Comments
 (0)