Skip to content

Commit e2294f2

Browse files
author
Mariano Converti
committed
# added support for OpenIdConnectDiscoveryDocument in TokenRestrictionTemplate
# added support for Widevine (WIP)
1 parent 9a3fd64 commit e2294f2

File tree

6 files changed

+130
-32
lines changed

6 files changed

+130
-32
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.microsoft.windowsazure.services.media.implementation.templates.tokenrestriction;
2+
3+
public final class ErrorMessages {
4+
5+
public static final String PRIMARY_VERIFICATIONKEY_AND_OPENIDCONNECTDISCOVERYDOCUMENT_ARE_NULL
6+
= "Both PrimaryVerificationKey and OpenIdConnectDiscoveryDocument are null.";
7+
8+
public static final String OPENIDDISCOVERYURI_STRING_IS_NULL_OR_EMPTY
9+
= "OpenIdConnectDiscoveryDocument.OpenIdDiscoveryUri string value is null or empty.";
10+
11+
public static final String OPENIDDISCOVERYURI_STRING_IS_NOT_ABSOLUTE_URI
12+
= "String representation of OpenIdConnectDiscoveryDocument.OpenIdDiscoveryUri is not valid absolute Uri.";
13+
14+
private ErrorMessages() {
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.microsoft.windowsazure.services.media.implementation.templates.tokenrestriction;
2+
3+
import javax.xml.bind.annotation.XmlAccessType;
4+
import javax.xml.bind.annotation.XmlAccessorType;
5+
import javax.xml.bind.annotation.XmlElement;
6+
import javax.xml.bind.annotation.XmlType;
7+
8+
@XmlAccessorType(XmlAccessType.FIELD)
9+
@XmlType(name = "OpenIdConnectDiscoveryDocument")
10+
public class OpenIdConnectDiscoveryDocument {
11+
12+
@XmlElement(name = "OpenIdDiscoveryUri")
13+
private String openIdDiscoveryUri;
14+
15+
/**
16+
* @return the openIdDiscoveryUri
17+
*/
18+
public String getOpenIdDiscoveryUri() {
19+
return openIdDiscoveryUri;
20+
}
21+
22+
/**
23+
* @param openIdDiscoveryUri the openIdDiscoveryUri to set
24+
*/
25+
public void setOpenIdDiscoveryUri(String openIdDiscoveryUri) {
26+
this.openIdDiscoveryUri = openIdDiscoveryUri;
27+
}
28+
29+
}

services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/templates/tokenrestriction/TokenRestrictionTemplate.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ public class TokenRestrictionTemplate {
3434

3535
@XmlElement(name = "TokenType")
3636
private TokenType tokenType;
37+
38+
@XmlElement(name = "OpenIdConnectDiscoveryDocument")
39+
private OpenIdConnectDiscoveryDocument openIdConnectDiscoveryDocument;
3740

3841
@SuppressWarnings("unused")
3942
private TokenRestrictionTemplate() {
@@ -146,4 +149,21 @@ public TokenRestrictionTemplate setAlternateVerificationKeys(List<TokenVerificat
146149
this.alternateVerificationKeys = alternateVerificationKeys;
147150
return this;
148151
}
152+
153+
/**
154+
* @return the alternateVerificationKeys
155+
*/
156+
public OpenIdConnectDiscoveryDocument getOpenIdConnectDiscoveryDocument() {
157+
return openIdConnectDiscoveryDocument;
158+
}
159+
160+
/**
161+
* @param alternateVerificationKeys the alternateVerificationKeys to set
162+
* @return this
163+
*/
164+
public TokenRestrictionTemplate setOpenIdConnectDiscoveryDocument(OpenIdConnectDiscoveryDocument openIdConnectDiscoveryDocument) {
165+
this.openIdConnectDiscoveryDocument = openIdConnectDiscoveryDocument;
166+
return this;
167+
}
168+
149169
}

services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/templates/tokenrestriction/TokenRestrictionTemplateSerializer.java

Lines changed: 54 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import java.io.File;
44
import java.io.StringReader;
55
import java.io.StringWriter;
6+
import java.net.MalformedURLException;
7+
import java.net.URL;
68
import java.net.URLEncoder;
79
import java.security.InvalidKeyException;
810
import java.security.NoSuchAlgorithmException;
@@ -37,16 +39,38 @@ private TokenRestrictionTemplateSerializer() {
3739
}
3840

3941
public static String serialize(TokenRestrictionTemplate template) throws JAXBException {
42+
43+
if (template.getPrimaryVerificationKey() == null && template.getOpenIdConnectDiscoveryDocument() == null) {
44+
throw new IllegalArgumentException(
45+
ErrorMessages.PRIMARY_VERIFICATIONKEY_AND_OPENIDCONNECTDISCOVERYDOCUMENT_ARE_NULL);
46+
}
47+
48+
if (template.getOpenIdConnectDiscoveryDocument() != null) {
49+
if (template.getOpenIdConnectDiscoveryDocument().getOpenIdDiscoveryUri() == null
50+
|| template.getOpenIdConnectDiscoveryDocument().getOpenIdDiscoveryUri().isEmpty()) {
51+
throw new IllegalArgumentException(ErrorMessages.OPENIDDISCOVERYURI_STRING_IS_NULL_OR_EMPTY);
52+
}
53+
54+
boolean openIdDiscoveryUrlValid = true;
55+
try {
56+
new URL(template.getOpenIdConnectDiscoveryDocument().getOpenIdDiscoveryUri());
57+
} catch (MalformedURLException e) {
58+
openIdDiscoveryUrlValid = false;
59+
}
60+
61+
if (!openIdDiscoveryUrlValid) {
62+
throw new IllegalArgumentException(ErrorMessages.OPENIDDISCOVERYURI_STRING_IS_NOT_ABSOLUTE_URI);
63+
}
64+
}
65+
4066
StringWriter writer = new StringWriter();
4167
JAXBContext context = JAXBContext.newInstance(TokenRestrictionTemplate.class);
4268
Marshaller m = context.createMarshaller();
4369
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
4470
m.setProperty("com.sun.xml.bind.namespacePrefixMapper", new NamespacePrefixMapper() {
4571
@Override
4672
public String[] getPreDeclaredNamespaceUris() {
47-
return new String[] {
48-
XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI
49-
};
73+
return new String[] { XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI };
5074
}
5175

5276
@Override
@@ -101,8 +125,8 @@ private static String urlEncode(String toEncode) {
101125
}
102126

103127
public static String generateTestToken(TokenRestrictionTemplate tokenTemplate, TokenVerificationKey signingKeyToUse,
104-
UUID keyIdForContentKeyIdentifierClaim, Date tokenExpiration, Date notBefore) {
105-
128+
UUID keyIdForContentKeyIdentifierClaim, Date tokenExpiration, Date notBefore) {
129+
106130
if (tokenTemplate == null) {
107131
throw new NullPointerException("tokenTemplate");
108132
}
@@ -117,61 +141,63 @@ public static String generateTestToken(TokenRestrictionTemplate tokenTemplate, T
117141
cal.add(Calendar.MINUTE, 10);
118142
tokenExpiration = cal.getTime();
119143
}
120-
144+
121145
if (notBefore == null) {
122146
Calendar cal = Calendar.getInstance();
123147
cal.setTime(new Date());
124148
cal.add(Calendar.MINUTE, -5);
125149
notBefore = cal.getTime();
126150
}
127-
151+
128152
if (tokenTemplate.getTokenType().equals(TokenType.SWT)) {
129-
return generateTestTokenSWT(tokenTemplate, signingKeyToUse, keyIdForContentKeyIdentifierClaim, tokenExpiration);
153+
return generateTestTokenSWT(tokenTemplate, signingKeyToUse, keyIdForContentKeyIdentifierClaim,
154+
tokenExpiration);
130155
} else {
131-
return generateTestTokenJWT(tokenTemplate, signingKeyToUse, keyIdForContentKeyIdentifierClaim, tokenExpiration, notBefore);
156+
return generateTestTokenJWT(tokenTemplate, signingKeyToUse, keyIdForContentKeyIdentifierClaim,
157+
tokenExpiration, notBefore);
132158
}
133159
}
134160

135-
public static String generateTestTokenJWT(TokenRestrictionTemplate tokenTemplate, TokenVerificationKey signingKeyToUse,
136-
UUID keyIdForContentKeyIdentifierClaim, Date tokenExpiration, Date notBefore) {
137-
161+
public static String generateTestTokenJWT(TokenRestrictionTemplate tokenTemplate,
162+
TokenVerificationKey signingKeyToUse, UUID keyIdForContentKeyIdentifierClaim, Date tokenExpiration,
163+
Date notBefore) {
164+
138165
SymmetricVerificationKey signingKey = (SymmetricVerificationKey) signingKeyToUse;
139166
SecretKeySpec secretKey = new SecretKeySpec(signingKey.getKeyValue(), "HmacSHA256");
140-
167+
141168
// Mapping Claims.
142169
Map<String, Object> claims = new HashMap<String, Object>();
143170
for (TokenClaim claim : tokenTemplate.getRequiredClaims()) {
144171
String claimValue = claim.getClaimValue();
145172
if (claimValue == null && claim.getClaimType().equals(TokenClaim.getContentKeyIdentifierClaimType())) {
146173
if (keyIdForContentKeyIdentifierClaim == null) {
147-
throw new IllegalArgumentException(String.format("The 'keyIdForContentKeyIdentifierClaim' parameter cannot be null when the token template contains a required '%s' claim type.", TokenClaim.getContentKeyIdentifierClaimType()));
174+
throw new IllegalArgumentException(String.format(
175+
"The 'keyIdForContentKeyIdentifierClaim' parameter cannot be null when the token template contains a required '%s' claim type.",
176+
TokenClaim.getContentKeyIdentifierClaimType()));
148177
}
149178
claimValue = keyIdForContentKeyIdentifierClaim.toString();
150179
}
151-
claims.put(claim.getClaimType(), claimValue);
180+
claims.put(claim.getClaimType(), claimValue);
152181
}
153182

154-
return Jwts.builder()
155-
.setHeaderParam("typ", "JWT")
156-
.setClaims(claims)
157-
.setIssuer(tokenTemplate.getIssuer().toString())
158-
.setAudience(tokenTemplate.getAudience().toString())
159-
.setIssuedAt(notBefore)
160-
.setExpiration(tokenExpiration)
161-
.signWith(SignatureAlgorithm.HS256, secretKey)
183+
return Jwts.builder().setHeaderParam("typ", "JWT").setClaims(claims)
184+
.setIssuer(tokenTemplate.getIssuer().toString()).setAudience(tokenTemplate.getAudience().toString())
185+
.setIssuedAt(notBefore).setExpiration(tokenExpiration).signWith(SignatureAlgorithm.HS256, secretKey)
162186
.compact();
163187
}
164-
165-
public static String generateTestTokenSWT(TokenRestrictionTemplate tokenTemplate, TokenVerificationKey signingKeyToUse,
166-
UUID keyIdForContentKeyIdentifierClaim, Date tokenExpiration) {
167-
188+
189+
public static String generateTestTokenSWT(TokenRestrictionTemplate tokenTemplate,
190+
TokenVerificationKey signingKeyToUse, UUID keyIdForContentKeyIdentifierClaim, Date tokenExpiration) {
191+
168192
StringBuilder builder = new StringBuilder();
169193

170194
for (TokenClaim claim : tokenTemplate.getRequiredClaims()) {
171195
String claimValue = claim.getClaimValue();
172196
if (claim.getClaimType().equals(TokenClaim.getContentKeyIdentifierClaimType())) {
173197
if (keyIdForContentKeyIdentifierClaim == null) {
174-
throw new IllegalArgumentException(String.format("The 'keyIdForContentKeyIdentifierClaim' parameter cannot be null when the token template contains a required '%s' claim type.", TokenClaim.getContentKeyIdentifierClaimType()));
198+
throw new IllegalArgumentException(String.format(
199+
"The 'keyIdForContentKeyIdentifierClaim' parameter cannot be null when the token template contains a required '%s' claim type.",
200+
TokenClaim.getContentKeyIdentifierClaimType()));
175201
}
176202
claimValue = keyIdForContentKeyIdentifierClaim.toString();
177203
}

services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/models/AssetDeliveryPolicyConfigurationKey.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@ public enum AssetDeliveryPolicyConfigurationKey {
3535
/** The PlayReady Custom Attributes to add to the PlayReady Content Header. */
3636
PlayReadyCustomAttributes(5),
3737
/** The initialization vector to use for envelope encryption. */
38-
EnvelopeEncryptionIV(6);
39-
40-
38+
EnvelopeEncryptionIV(6),
39+
/** Widevine DRM Acquisition Url to use for common encryption. */
40+
WidevineLicenseAcquisitionUrl(7);
41+
4142

4243
/** The AssetDeliveryPolicyType code. */
4344
private int assetDeliveryPolicyConfigurationKey;
@@ -84,6 +85,8 @@ public static AssetDeliveryPolicyConfigurationKey fromCode(int option) {
8485
return AssetDeliveryPolicyConfigurationKey.PlayReadyCustomAttributes;
8586
case 6:
8687
return AssetDeliveryPolicyConfigurationKey.EnvelopeEncryptionIV;
88+
case 7:
89+
return AssetDeliveryPolicyConfigurationKey.WidevineLicenseAcquisitionUrl;
8790
default:
8891
throw new InvalidParameterException("option");
8992
}

services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/models/ContentKeyDeliveryType.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ public enum ContentKeyDeliveryType {
2727
/** Use PlayReady License acquisition protocol. */
2828
PlayReadyLicense(1),
2929
/** Use MPEG Baseline HTTP key protocol. */
30-
BaselineHttp(2);
30+
BaselineHttp(2),
31+
/** Use Widevine license acquisition protocol. */
32+
Widevine(3);
3133

3234
/** The AssetDeliveryPolicyType code. */
3335
private int contentKeyDeliveryType;
@@ -66,6 +68,8 @@ public static ContentKeyDeliveryType fromCode(int option) {
6668
return ContentKeyDeliveryType.PlayReadyLicense;
6769
case 2:
6870
return ContentKeyDeliveryType.BaselineHttp;
71+
case 3:
72+
return ContentKeyDeliveryType.Widevine;
6973
default:
7074
throw new InvalidParameterException("option");
7175
}

0 commit comments

Comments
 (0)