CSRFServlet.java
6.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
* Decompiled with CFR 0_118.
*
* Could not load the following classes:
* com.adobe.granite.crypto.CryptoException
* com.adobe.granite.crypto.CryptoSupport
* com.adobe.granite.oauth.jwt.JwsBuilder
* com.adobe.granite.oauth.jwt.JwsBuilderFactory
* javax.servlet.ServletException
* org.apache.felix.scr.annotations.Activate
* org.apache.felix.scr.annotations.Modified
* org.apache.felix.scr.annotations.Property
* org.apache.felix.scr.annotations.Reference
* org.apache.felix.scr.annotations.sling.SlingServlet
* org.apache.oltu.commons.encodedtoken.TokenDecoder
* org.apache.oltu.commons.json.CustomizableEntity
* org.apache.oltu.oauth2.jwt.ClaimsSet
* org.apache.oltu.oauth2.jwt.JWT
* org.apache.oltu.oauth2.jwt.JWT$Builder
* org.apache.oltu.oauth2.jwt.io.JWTClaimsSetWriter
* org.apache.oltu.oauth2.jwt.io.JWTReader
* org.apache.sling.api.SlingHttpServletRequest
* org.apache.sling.api.SlingHttpServletResponse
* org.apache.sling.api.servlets.SlingSafeMethodsServlet
* org.apache.sling.commons.osgi.PropertiesUtil
* org.json.JSONWriter
* org.osgi.framework.BundleContext
* org.slf4j.Logger
* org.slf4j.LoggerFactory
*/
package com.adobe.granite.csrf.impl;
import com.adobe.granite.crypto.CryptoException;
import com.adobe.granite.crypto.CryptoSupport;
import com.adobe.granite.oauth.jwt.JwsBuilder;
import com.adobe.granite.oauth.jwt.JwsBuilderFactory;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Map;
import javax.servlet.ServletException;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Modified;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.sling.SlingServlet;
import org.apache.oltu.commons.encodedtoken.TokenDecoder;
import org.apache.oltu.commons.json.CustomizableEntity;
import org.apache.oltu.oauth2.jwt.ClaimsSet;
import org.apache.oltu.oauth2.jwt.JWT;
import org.apache.oltu.oauth2.jwt.io.JWTClaimsSetWriter;
import org.apache.oltu.oauth2.jwt.io.JWTReader;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.json.JSONWriter;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/*
* This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6.
*/
@SlingServlet(resourceTypes={"granite/csrf/token"}, extensions={"json"}, metatype=1, description="Servlet that return the CSRF token for a given user.", label="Adobe Granite CSRF Servlet")
@Property(label="CSRF Token Expires In", description="The lifetime in seconds of the csrf token (min 600 seconds/10 minutes)", name="csrf.token.expires.in", longValue={600})
public class CSRFServlet
extends SlingSafeMethodsServlet {
private static final long serialVersionUID = 1;
static final long CSRF_TOKEN_EXPIRES_IN_DEFAULT = 600;
private final Logger logger = LoggerFactory.getLogger(CSRFServlet.class);
@Reference
private JwsBuilderFactory jwsBuilderFactory;
@Reference
private CryptoSupport cryptoSupport;
private long csrfTokenExpiresIn;
@Activate
@Modified
private void activate(BundleContext context, Map<String, Object> config) {
this.csrfTokenExpiresIn = PropertiesUtil.toLong((Object)config.get("csrf.token.expires.in"), (long)600);
if (this.csrfTokenExpiresIn < 600) {
this.logger.warn("The lifetime in seconds of the csrf token must be minimum 600 seconds/10 minutes, defaulting lifetime to 600 seconds/10 minutes");
this.csrfTokenExpiresIn = 600;
}
}
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
JSONWriter writer = new JSONWriter((Writer)response.getWriter());
writer.object();
try {
if (request.getAuthType() != null) {
String user = request.getRemoteUser();
String csrfToken = this.getCSRFToken(user);
writer.key("token").value((Object)csrfToken);
} else {
this.logger.debug("doGet: CSRF token available only for authenticated users");
}
response.setContentType("application/json");
response.setCharacterEncoding("utf8");
response.setHeader("Cache-Control", "no-cache");
response.setStatus(200);
writer.endObject();
}
catch (CryptoException e) {
this.logger.error("doGet: failed to generate CSRF token", (Throwable)e);
response.sendError(500);
}
}
private String getCSRFToken(String user) throws NumberFormatException, CryptoException {
StringBuilder sb = new StringBuilder();
String token = this.jwsBuilderFactory.getInstance("HS256").setSubject(user).setExpiresIn(this.csrfTokenExpiresIn).setCustomClaimsSetField("scope", (Object)":aem_csrf_token_value").build();
JWT jws = (JWT)new JWTReader().read(token);
long iat = jws.getClaimsSet().getIssuedAt();
JWT jwt = new JWT.Builder().setClaimsSetIssuedAt(iat).setClaimsSetExpirationTime(iat + this.csrfTokenExpiresIn).build();
String payload = new JWTClaimsSetWriter().write((CustomizableEntity)jwt.getClaimsSet());
sb.append(TokenDecoder.base64Encode((String)payload)).append(".").append(jws.getSignature());
return sb.toString();
}
protected void bindJwsBuilderFactory(JwsBuilderFactory jwsBuilderFactory) {
this.jwsBuilderFactory = jwsBuilderFactory;
}
protected void unbindJwsBuilderFactory(JwsBuilderFactory jwsBuilderFactory) {
if (this.jwsBuilderFactory == jwsBuilderFactory) {
this.jwsBuilderFactory = null;
}
}
protected void bindCryptoSupport(CryptoSupport cryptoSupport) {
this.cryptoSupport = cryptoSupport;
}
protected void unbindCryptoSupport(CryptoSupport cryptoSupport) {
if (this.cryptoSupport == cryptoSupport) {
this.cryptoSupport = null;
}
}
}