From b4520c170ed0b080e75c926010f9a93e01cbc185 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 24 Jun 2015 15:36:55 -0400 Subject: [PATCH 001/465] ID Token carried through as parsed JWT instead of string, closes #832 --- .../client/OIDCAuthenticationFilter.java | 2 +- .../client/OIDCAuthenticationProvider.java | 39 ++++++++---------- .../openid/connect/model/DefaultUserInfo.java | 28 ++++++++++++- .../model/OIDCAuthenticationToken.java | 40 +++++++++++++++---- 4 files changed, 76 insertions(+), 33 deletions(-) diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java index dd4b25d110..a45fc0e099 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java @@ -584,7 +584,7 @@ protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOE // construct an OIDCAuthenticationToken and return a Authentication object w/the userId and the idToken - OIDCAuthenticationToken token = new OIDCAuthenticationToken(userId, idClaims.getIssuer(), serverConfig, idTokenValue, accessTokenValue, refreshTokenValue); + OIDCAuthenticationToken token = new OIDCAuthenticationToken(userId, idClaims.getIssuer(), serverConfig, idToken, accessTokenValue, refreshTokenValue); Authentication authentication = this.getAuthenticationManager().authenticate(token); diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationProvider.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationProvider.java index 04987c4f0c..f614038984 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationProvider.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationProvider.java @@ -62,30 +62,23 @@ public Authentication authenticate(final Authentication authentication) throws A OIDCAuthenticationToken token = (OIDCAuthenticationToken) authentication; - try { - - // get the ID Token value out - String idTokenString = token.getIdTokenValue(); - JWT idToken = JWTParser.parse(idTokenString); - - // load the user info if we can - UserInfo userInfo = userInfoFetcher.loadUserInfo(token); - - if (userInfo == null) { - // user info not found -- could be an error, could be fine - } else { - // if we found userinfo, double check it - if (!Strings.isNullOrEmpty(userInfo.getSub()) && !userInfo.getSub().equals(token.getSub())) { - // the userinfo came back and the user_id fields don't match what was in the id_token - throw new UsernameNotFoundException("user_id mismatch between id_token and user_info call: " + token.getSub() + " / " + userInfo.getSub()); - } + // get the ID Token value out + JWT idToken = token.getIdToken(); + + // load the user info if we can + UserInfo userInfo = userInfoFetcher.loadUserInfo(token); + + if (userInfo == null) { + // user info not found -- could be an error, could be fine + } else { + // if we found userinfo, double check it + if (!Strings.isNullOrEmpty(userInfo.getSub()) && !userInfo.getSub().equals(token.getSub())) { + // the userinfo came back and the user_id fields don't match what was in the id_token + throw new UsernameNotFoundException("user_id mismatch between id_token and user_info call: " + token.getSub() + " / " + userInfo.getSub()); } - - return createAuthenticationToken(token, authoritiesMapper.mapAuthorities(idToken, userInfo), userInfo); - } catch (ParseException e) { - logger.error("Unable to parse ID token in the token"); - return null; } + + return createAuthenticationToken(token, authoritiesMapper.mapAuthorities(idToken, userInfo), userInfo); } return null; @@ -104,7 +97,7 @@ protected Authentication createAuthenticationToken(OIDCAuthenticationToken token return new OIDCAuthenticationToken(token.getSub(), token.getIssuer(), userInfo, authorities, - token.getIdTokenValue(), token.getAccessTokenValue(), token.getRefreshTokenValue()); + token.getIdToken(), token.getAccessTokenValue(), token.getRefreshTokenValue()); } /** diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultUserInfo.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultUserInfo.java index 9743677c17..2bbb959cc5 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultUserInfo.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultUserInfo.java @@ -16,6 +16,10 @@ *******************************************************************************/ package org.mitre.openid.connect.model; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + import javax.persistence.Basic; import javax.persistence.Column; import javax.persistence.Convert; @@ -32,6 +36,7 @@ import org.mitre.openid.connect.model.convert.JsonObjectStringConverter; import com.google.gson.JsonObject; +import com.google.gson.JsonParser; @Entity @Table(name="user_info") @@ -70,7 +75,7 @@ public class DefaultUserInfo implements UserInfo { private Address address; private String updatedTime; private String birthdate; - private JsonObject src; // source JSON if this is loaded remotely + private transient JsonObject src; // source JSON if this is loaded remotely /** @@ -727,5 +732,26 @@ public boolean equals(Object obj) { } return true; } + + + /* + * Custom serialization to handle the JSON object + */ + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + if (src == null) { + out.writeObject(null); + } else { + out.writeObject(src.toString()); + } + } + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + Object o = in.readObject(); + if (o != null) { + JsonParser parser = new JsonParser(); + src = parser.parse((String)o).getAsJsonObject(); + } + } } diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/OIDCAuthenticationToken.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/OIDCAuthenticationToken.java index 20cb389f68..d6bd760289 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/OIDCAuthenticationToken.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/OIDCAuthenticationToken.java @@ -16,6 +16,10 @@ *******************************************************************************/ package org.mitre.openid.connect.model; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.text.ParseException; import java.util.ArrayList; import java.util.Collection; @@ -24,6 +28,8 @@ import org.springframework.security.core.GrantedAuthority; import com.google.common.collect.ImmutableMap; +import com.nimbusds.jwt.JWT; +import com.nimbusds.jwt.JWTParser; /** * @@ -35,14 +41,14 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken { private static final long serialVersionUID = 22100073066377804L; private final ImmutableMap principal; - private final String idTokenValue; // string representation of the id token private final String accessTokenValue; // string representation of the access token private final String refreshTokenValue; // string representation of the refresh token + private transient JWT idToken; // this needs a custom serializer private final String issuer; // issuer URL (parsed from the id token) private final String sub; // user id (parsed from the id token) private final transient ServerConfiguration serverConfiguration; // server configuration used to fulfill this token, don't serialize it - private final UserInfo userInfo; // user info container, don't serialize it b/c it might be huge and can be re-fetched + private final UserInfo userInfo; // user info container /** * Constructs OIDCAuthenticationToken with a full set of authorities, marking this as authenticated. @@ -57,7 +63,7 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken { */ public OIDCAuthenticationToken(String subject, String issuer, UserInfo userInfo, Collection authorities, - String idTokenValue, String accessTokenValue, String refreshTokenValue) { + JWT idToken, String accessTokenValue, String refreshTokenValue) { super(authorities); @@ -65,7 +71,7 @@ public OIDCAuthenticationToken(String subject, String issuer, this.userInfo = userInfo; this.sub = subject; this.issuer = issuer; - this.idTokenValue = idTokenValue; + this.idToken = idToken; this.accessTokenValue = accessTokenValue; this.refreshTokenValue = refreshTokenValue; @@ -85,14 +91,14 @@ public OIDCAuthenticationToken(String subject, String issuer, */ public OIDCAuthenticationToken(String subject, String issuer, ServerConfiguration serverConfiguration, - String idTokenValue, String accessTokenValue, String refreshTokenValue) { + JWT idToken, String accessTokenValue, String refreshTokenValue) { super(new ArrayList(0)); this.principal = ImmutableMap.of("sub", subject, "iss", issuer); this.sub = subject; this.issuer = issuer; - this.idTokenValue = idTokenValue; + this.idToken = idToken; this.accessTokenValue = accessTokenValue; this.refreshTokenValue = refreshTokenValue; @@ -129,8 +135,8 @@ public String getSub() { /** * @return the idTokenValue */ - public String getIdTokenValue() { - return idTokenValue; + public JWT getIdToken() { + return idToken; } /** @@ -168,5 +174,23 @@ public UserInfo getUserInfo() { return userInfo; } + /* + * Custom serialization to handle the JSON object + */ + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + if (idToken == null) { + out.writeObject(null); + } else { + out.writeObject(idToken.serialize()); + } + } + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException, ParseException { + in.defaultReadObject(); + Object o = in.readObject(); + if (o != null) { + idToken = JWTParser.parse((String)o); + } + } } From 7df3597757f59b959c113978f9d3b5b5b21e034a Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 24 Jun 2015 15:59:13 -0400 Subject: [PATCH 002/465] split client's auth token into pending and authorized classes --- .../client/OIDCAuthenticationFilter.java | 14 +- .../client/OIDCAuthenticationProvider.java | 13 +- .../connect/client/UserInfoFetcher.java | 4 +- .../model/OIDCAuthenticationToken.java | 41 ----- .../model/PendingOIDCAuthenticationToken.java | 157 ++++++++++++++++++ 5 files changed, 171 insertions(+), 58 deletions(-) create mode 100644 openid-connect-common/src/main/java/org/mitre/openid/connect/model/PendingOIDCAuthenticationToken.java diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java index a45fc0e099..9070d91e9c 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java @@ -44,7 +44,7 @@ import org.mitre.openid.connect.client.service.ServerConfigurationService; import org.mitre.openid.connect.client.service.impl.StaticAuthRequestOptionsService; import org.mitre.openid.connect.config.ServerConfiguration; -import org.mitre.openid.connect.model.OIDCAuthenticationToken; +import org.mitre.openid.connect.model.PendingOIDCAuthenticationToken; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpMethod; import org.springframework.http.client.ClientHttpRequest; @@ -578,14 +578,12 @@ protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOE + "ID Token to the session " + NONCE_SESSION_VARIABLE + " failed. Expected " + storedNonce + " got " + nonce + "."); } - // pull the subject (user id) out as a claim on the id_token - - String userId = idClaims.getSubject(); - - // construct an OIDCAuthenticationToken and return a Authentication object w/the userId and the idToken - - OIDCAuthenticationToken token = new OIDCAuthenticationToken(userId, idClaims.getIssuer(), serverConfig, idToken, accessTokenValue, refreshTokenValue); + // construct an PendingOIDCAuthenticationToken and return a Authentication object w/the userId and the idToken + PendingOIDCAuthenticationToken token = new PendingOIDCAuthenticationToken(idClaims.getSubject(), idClaims.getIssuer(), + serverConfig, + idToken, accessTokenValue, refreshTokenValue); + Authentication authentication = this.getAuthenticationManager().authenticate(token); return authentication; diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationProvider.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationProvider.java index f614038984..156ff4dd73 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationProvider.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationProvider.java @@ -16,10 +16,10 @@ *******************************************************************************/ package org.mitre.openid.connect.client; -import java.text.ParseException; import java.util.Collection; import org.mitre.openid.connect.model.OIDCAuthenticationToken; +import org.mitre.openid.connect.model.PendingOIDCAuthenticationToken; import org.mitre.openid.connect.model.UserInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,10 +31,9 @@ import com.google.common.base.Strings; import com.nimbusds.jwt.JWT; -import com.nimbusds.jwt.JWTParser; /** - * @author nemonik + * @author nemonik, Justin Richer * */ public class OIDCAuthenticationProvider implements AuthenticationProvider { @@ -58,9 +57,9 @@ public Authentication authenticate(final Authentication authentication) throws A return null; } - if (authentication instanceof OIDCAuthenticationToken) { + if (authentication instanceof PendingOIDCAuthenticationToken) { - OIDCAuthenticationToken token = (OIDCAuthenticationToken) authentication; + PendingOIDCAuthenticationToken token = (PendingOIDCAuthenticationToken) authentication; // get the ID Token value out JWT idToken = token.getIdToken(); @@ -93,7 +92,7 @@ public Authentication authenticate(final Authentication authentication) throws A * @param userInfo * @return */ - protected Authentication createAuthenticationToken(OIDCAuthenticationToken token, Collection authorities, UserInfo userInfo) { + protected Authentication createAuthenticationToken(PendingOIDCAuthenticationToken token, Collection authorities, UserInfo userInfo) { return new OIDCAuthenticationToken(token.getSub(), token.getIssuer(), userInfo, authorities, @@ -116,6 +115,6 @@ public void setAuthoritiesMapper(OIDCAuthoritiesMapper authoritiesMapper) { */ @Override public boolean supports(Class authentication) { - return OIDCAuthenticationToken.class.isAssignableFrom(authentication); + return PendingOIDCAuthenticationToken.class.isAssignableFrom(authentication); } } diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/UserInfoFetcher.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/UserInfoFetcher.java index 36ed963915..3cb0fe1975 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/UserInfoFetcher.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/UserInfoFetcher.java @@ -25,7 +25,7 @@ import org.mitre.openid.connect.config.ServerConfiguration; import org.mitre.openid.connect.config.ServerConfiguration.UserInfoTokenMethod; import org.mitre.openid.connect.model.DefaultUserInfo; -import org.mitre.openid.connect.model.OIDCAuthenticationToken; +import org.mitre.openid.connect.model.PendingOIDCAuthenticationToken; import org.mitre.openid.connect.model.UserInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,7 +52,7 @@ public class UserInfoFetcher { */ private static final Logger logger = LoggerFactory.getLogger(UserInfoFetcher.class); - public UserInfo loadUserInfo(final OIDCAuthenticationToken token) { + public UserInfo loadUserInfo(final PendingOIDCAuthenticationToken token) { ServerConfiguration serverConfiguration = token.getServerConfiguration(); diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/OIDCAuthenticationToken.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/OIDCAuthenticationToken.java index d6bd760289..65a71812ee 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/OIDCAuthenticationToken.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/OIDCAuthenticationToken.java @@ -20,10 +20,8 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.text.ParseException; -import java.util.ArrayList; import java.util.Collection; -import org.mitre.openid.connect.config.ServerConfiguration; import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.core.GrantedAuthority; @@ -47,7 +45,6 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken { private final String issuer; // issuer URL (parsed from the id token) private final String sub; // user id (parsed from the id token) - private final transient ServerConfiguration serverConfiguration; // server configuration used to fulfill this token, don't serialize it private final UserInfo userInfo; // user info container /** @@ -75,40 +72,9 @@ public OIDCAuthenticationToken(String subject, String issuer, this.accessTokenValue = accessTokenValue; this.refreshTokenValue = refreshTokenValue; - this.serverConfiguration = null; // we don't need a server config anymore - setAuthenticated(true); } - /** - * Constructs OIDCAuthenticationToken for use as a data shuttle from the filter to the auth provider. - * - * Set to not-authenticated. - * - * Constructs a Principal out of the subject and issuer. - * @param sub - * @param idToken - */ - public OIDCAuthenticationToken(String subject, String issuer, - ServerConfiguration serverConfiguration, - JWT idToken, String accessTokenValue, String refreshTokenValue) { - - super(new ArrayList(0)); - - this.principal = ImmutableMap.of("sub", subject, "iss", issuer); - this.sub = subject; - this.issuer = issuer; - this.idToken = idToken; - this.accessTokenValue = accessTokenValue; - this.refreshTokenValue = refreshTokenValue; - - this.userInfo = null; // we don't have a UserInfo yet - - this.serverConfiguration = serverConfiguration; - - - setAuthenticated(false); - } /* * (non-Javadoc) @@ -153,13 +119,6 @@ public String getRefreshTokenValue() { return refreshTokenValue; } - /** - * @return the serverConfiguration - */ - public ServerConfiguration getServerConfiguration() { - return serverConfiguration; - } - /** * @return the issuer */ diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/PendingOIDCAuthenticationToken.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/PendingOIDCAuthenticationToken.java new file mode 100644 index 0000000000..659daa3699 --- /dev/null +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/PendingOIDCAuthenticationToken.java @@ -0,0 +1,157 @@ +/******************************************************************************* + * Copyright 2015 The MITRE Corporation + * and the MIT Kerberos and Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +package org.mitre.openid.connect.model; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.text.ParseException; +import java.util.ArrayList; + +import org.mitre.openid.connect.config.ServerConfiguration; +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; + +import com.google.common.collect.ImmutableMap; +import com.nimbusds.jwt.JWT; +import com.nimbusds.jwt.JWTParser; + +/** + * AuthenticationToken for use as a data shuttle from the filter to the auth provider. + * + * @author jricher + * + */ +public class PendingOIDCAuthenticationToken extends AbstractAuthenticationToken { + + private static final long serialVersionUID = 22100073066377804L; + + private final ImmutableMap principal; + private final String accessTokenValue; // string representation of the access token + private final String refreshTokenValue; // string representation of the refresh token + private transient JWT idToken; // this needs a custom serializer + private final String issuer; // issuer URL (parsed from the id token) + private final String sub; // user id (parsed from the id token) + + private final transient ServerConfiguration serverConfiguration; // server configuration used to fulfill this token, don't serialize it + + /** + * Constructs OIDCAuthenticationToken for use as a data shuttle from the filter to the auth provider. + * + * Set to not-authenticated. + * + * Constructs a Principal out of the subject and issuer. + * @param sub + * @param idToken + */ + public PendingOIDCAuthenticationToken (String subject, String issuer, + ServerConfiguration serverConfiguration, + JWT idToken, String accessTokenValue, String refreshTokenValue) { + + super(new ArrayList(0)); + + this.principal = ImmutableMap.of("sub", subject, "iss", issuer); + this.sub = subject; + this.issuer = issuer; + this.idToken = idToken; + this.accessTokenValue = accessTokenValue; + this.refreshTokenValue = refreshTokenValue; + + this.serverConfiguration = serverConfiguration; + + + setAuthenticated(false); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.security.core.Authentication#getCredentials() + */ + @Override + public Object getCredentials() { + return accessTokenValue; + } + + /** + * Get the principal of this object, an immutable map of the subject and issuer. + */ + @Override + public Object getPrincipal() { + return principal; + } + + public String getSub() { + return sub; + } + + /** + * @return the idTokenValue + */ + public JWT getIdToken() { + return idToken; + } + + /** + * @return the accessTokenValue + */ + public String getAccessTokenValue() { + return accessTokenValue; + } + + /** + * @return the refreshTokenValue + */ + public String getRefreshTokenValue() { + return refreshTokenValue; + } + + /** + * @return the serverConfiguration + */ + public ServerConfiguration getServerConfiguration() { + return serverConfiguration; + } + + /** + * @return the issuer + */ + public String getIssuer() { + return issuer; + } + + /* + * Custom serialization to handle the JSON object + */ + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + if (idToken == null) { + out.writeObject(null); + } else { + out.writeObject(idToken.serialize()); + } + } + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException, ParseException { + in.defaultReadObject(); + Object o = in.readObject(); + if (o != null) { + idToken = JWTParser.parse((String)o); + } + } + +} From b18bea6b9f5225dbf6bb9d0bdd45bf60c2168ff5 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 24 Jun 2015 16:21:31 -0400 Subject: [PATCH 003/465] switched connection pool to use HikariCP, closes #821 --- openid-connect-server-webapp/pom.xml | 8 ++++---- .../src/main/webapp/WEB-INF/data-context.xml | 6 +++--- pom.xml | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index 491cbca567..ae3fdc7ecf 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -107,10 +107,6 @@ log4j log4j - - commons-dbcp - commons-dbcp - org.hsqldb hsqldb @@ -128,5 +124,9 @@ jstl + + com.zaxxer + HikariCP-java6 + diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/data-context.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/data-context.xml index 663649b396..c1c8620dbd 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/data-context.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/data-context.xml @@ -21,10 +21,10 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd"> - + - - + + diff --git a/pom.xml b/pom.xml index b8b6fce83c..2f8433089b 100644 --- a/pom.xml +++ b/pom.xml @@ -389,11 +389,6 @@ org.eclipse.persistence.jpa 2.5.1 - - commons-dbcp - commons-dbcp - 1.4 - org.eclipse.persistence javax.persistence @@ -538,6 +533,11 @@ 3.9 + + com.zaxxer + HikariCP-java6 + 2.3.8 + From d2a393f7f9c55701ebe77f0c01593f8517081bb7 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 24 Jun 2015 17:14:01 -0400 Subject: [PATCH 004/465] converted error handlers to a single @ControllerAdvice class, closes #788 --- .../IntrospectingTokenService.java | 2 +- .../impl/JsonFileRegisteredClientService.java | 1 - .../oauth2/web/IntrospectionEndpoint.java | 14 ------ .../oauth2/web/OAuth2ExceptionHandler.java | 48 +++++++++++++++++++ .../java/org/mitre/oauth2/web/ScopeAPI.java | 13 ----- .../java/org/mitre/oauth2/web/TokenAPI.java | 13 ----- .../openid/connect/web/ApprovedSiteAPI.java | 12 ----- .../openid/connect/web/BlacklistAPI.java | 12 ----- .../mitre/openid/connect/web/ClientAPI.java | 12 ----- .../org/mitre/openid/connect/web/DataAPI.java | 13 ----- .../DynamicClientRegistrationEndpoint.java | 12 ----- ...ProtectedResourceRegistrationEndpoint.java | 12 ----- .../connect/web/ServerConfigInterceptor.java | 1 - .../mitre/openid/connect/web/StatsAPI.java | 12 ----- .../openid/connect/web/UserInfoEndpoint.java | 12 ----- .../openid/connect/web/WhitelistAPI.java | 12 ----- .../uma/web/AuthorizationRequestEndpoint.java | 11 ----- .../web/PermissionRegistrationEndpoint.java | 10 ---- .../web/ResourceSetRegistrationEndpoint.java | 11 ----- 19 files changed, 49 insertions(+), 184 deletions(-) create mode 100644 openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuth2ExceptionHandler.java diff --git a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/IntrospectingTokenService.java b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/IntrospectingTokenService.java index 42d239030c..0935fe529a 100644 --- a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/IntrospectingTokenService.java +++ b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/IntrospectingTokenService.java @@ -18,8 +18,8 @@ import java.io.IOException; import java.net.URI; -import java.util.Date; import java.util.Calendar; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Map; diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/JsonFileRegisteredClientService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/JsonFileRegisteredClientService.java index 984bf62214..2a511ed20a 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/JsonFileRegisteredClientService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/JsonFileRegisteredClientService.java @@ -20,7 +20,6 @@ package org.mitre.openid.connect.client.service.impl; import java.io.File; -import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/IntrospectionEndpoint.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/IntrospectionEndpoint.java index 1e9ad3a1c1..1762323b84 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/IntrospectionEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/IntrospectionEndpoint.java @@ -38,15 +38,11 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -78,9 +74,6 @@ public class IntrospectionEndpoint { @Autowired private ResourceSetService resourceSetService; - @Autowired - private WebResponseExceptionTranslator providerExceptionHandler; - /** * Logger for this class */ @@ -214,11 +207,4 @@ public String verify(@RequestParam("token") String tokenValue, } - @ExceptionHandler(OAuth2Exception.class) - public ResponseEntity handleException(Exception e) throws Exception { - logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); - return providerExceptionHandler.translate(e); - } - - } diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuth2ExceptionHandler.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuth2ExceptionHandler.java new file mode 100644 index 0000000000..35efd5c7c8 --- /dev/null +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuth2ExceptionHandler.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright 2015 The MITRE Corporation + * and the MIT Kerberos and Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +package org.mitre.oauth2.web; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; +import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +/** + * Controller helper that handles OAuth2 exceptions and propagates them as JSON errors. + * + * @author jricher + * + */ +@ControllerAdvice +public class OAuth2ExceptionHandler { + private static final Logger logger = LoggerFactory.getLogger(OAuth2ExceptionHandler.class); + + @Autowired + private WebResponseExceptionTranslator providerExceptionHandler; + + @ExceptionHandler(OAuth2Exception.class) + public ResponseEntity handleException(Exception e) throws Exception { + logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); + return providerExceptionHandler.translate(e); + } + +} diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/ScopeAPI.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/ScopeAPI.java index 2690525e29..70ed8f2a19 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/ScopeAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/ScopeAPI.java @@ -32,13 +32,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -60,9 +56,6 @@ public class ScopeAPI { @Autowired private SystemScopeService scopeService; - @Autowired - private WebResponseExceptionTranslator providerExceptionHandler; - /** * Logger for this class */ @@ -187,10 +180,4 @@ public String deleteScope(@PathVariable("id") Long id, ModelMap m) { return JsonErrorView.VIEWNAME; } } - - @ExceptionHandler(OAuth2Exception.class) - public ResponseEntity handleException(Exception e) throws Exception { - logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); - return providerExceptionHandler.translate(e); - } } diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/TokenAPI.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/TokenAPI.java index bbfb1b49b4..567ab7fcb2 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/TokenAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/TokenAPI.java @@ -36,13 +36,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -68,9 +64,6 @@ public class TokenAPI { @Autowired private OIDCTokenService oidcTokenService; - @Autowired - private WebResponseExceptionTranslator providerExceptionHandler; - /** * Logger for this class */ @@ -249,10 +242,4 @@ public String deleteRefreshTokenById(@PathVariable("id") Long id, ModelMap m, Pr return HttpCodeView.VIEWNAME; } } - - @ExceptionHandler(OAuth2Exception.class) - public ResponseEntity handleException(Exception e) throws Exception { - logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); - return providerExceptionHandler.translate(e); - } } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ApprovedSiteAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ApprovedSiteAPI.java index f5131c0069..0f71b8a8f9 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ApprovedSiteAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ApprovedSiteAPI.java @@ -34,13 +34,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -62,9 +58,6 @@ public class ApprovedSiteAPI { @Autowired private OAuth2TokenEntityService tokenServices; - @Autowired - private WebResponseExceptionTranslator providerExceptionHandler; - /** * Logger for this class */ @@ -136,9 +129,4 @@ public String getApprovedSite(@PathVariable("id") Long id, ModelMap m, Principal } - @ExceptionHandler(OAuth2Exception.class) - public ResponseEntity handleException(Exception e) throws Exception { - logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); - return providerExceptionHandler.translate(e); - } } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/BlacklistAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/BlacklistAPI.java index da149e3f23..39fe23c8ec 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/BlacklistAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/BlacklistAPI.java @@ -32,13 +32,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -68,9 +64,6 @@ public class BlacklistAPI { */ private static final Logger logger = LoggerFactory.getLogger(BlacklistAPI.class); - @Autowired - private WebResponseExceptionTranslator providerExceptionHandler; - private Gson gson = new Gson(); private JsonParser parser = new JsonParser(); @@ -213,9 +206,4 @@ public String getBlacklistedSite(@PathVariable("id") Long id, ModelMap m) { } - @ExceptionHandler(OAuth2Exception.class) - public ResponseEntity handleException(Exception e) throws Exception { - logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); - return providerExceptionHandler.translate(e); - } } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java index 225350d0f5..10dd47f25c 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java @@ -35,14 +35,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -82,9 +78,6 @@ public class ClientAPI { @Autowired private UserInfoService userInfoService; - @Autowired - private WebResponseExceptionTranslator providerExceptionHandler; - private JsonParser parser = new JsonParser(); private Gson gson = new GsonBuilder() @@ -405,9 +398,4 @@ public String apiShowClient(@PathVariable("id") Long id, Model model, Authentica } } - @ExceptionHandler(OAuth2Exception.class) - public ResponseEntity handleException(Exception e) throws Exception { - logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); - return providerExceptionHandler.translate(e); - } } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DataAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DataAPI.java index 1fcf0951df..992bd2de4c 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DataAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DataAPI.java @@ -33,13 +33,9 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -80,9 +76,6 @@ public class DataAPI { @Autowired private MITREidDataService_1_2 dataService_1_2; - @Autowired - private WebResponseExceptionTranslator providerExceptionHandler; - @RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE) public String importData(Reader in, Model m) throws IOException { @@ -151,10 +144,4 @@ public void exportData(HttpServletResponse resp, Principal prin) throws IOExcept } } - @ExceptionHandler(OAuth2Exception.class) - public ResponseEntity handleException(Exception e) throws Exception { - logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); - return providerExceptionHandler.translate(e); - } - } \ No newline at end of file diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java index 2258d3dee7..b542d30d85 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java @@ -45,15 +45,11 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails; -import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -92,9 +88,6 @@ public class DynamicClientRegistrationEndpoint { @Autowired private OIDCTokenService connectTokenService; - @Autowired - private WebResponseExceptionTranslator providerExceptionHandler; - /** * Logger for this class */ @@ -570,9 +563,4 @@ private OAuth2AccessTokenEntity fetchValidRegistrationToken(OAuth2Authentication } } - @ExceptionHandler(OAuth2Exception.class) - public ResponseEntity handleException(Exception e) throws Exception { - logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); - return providerExceptionHandler.translate(e); - } } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ProtectedResourceRegistrationEndpoint.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ProtectedResourceRegistrationEndpoint.java index d081b3a257..7c435d8514 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ProtectedResourceRegistrationEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ProtectedResourceRegistrationEndpoint.java @@ -44,15 +44,11 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails; -import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -92,9 +88,6 @@ public class ProtectedResourceRegistrationEndpoint { @Autowired private OIDCTokenService connectTokenService; - @Autowired - private WebResponseExceptionTranslator providerExceptionHandler; - /** * Logger for this class */ @@ -483,9 +476,4 @@ private OAuth2AccessTokenEntity fetchValidRegistrationToken(OAuth2Authentication } } - @ExceptionHandler(OAuth2Exception.class) - public ResponseEntity handleException(Exception e) throws Exception { - logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); - return providerExceptionHandler.translate(e); - } } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ServerConfigInterceptor.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ServerConfigInterceptor.java index ad833f4083..7dac1fe46d 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ServerConfigInterceptor.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ServerConfigInterceptor.java @@ -24,7 +24,6 @@ import org.mitre.openid.connect.config.ConfigurationPropertiesBean; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; /** diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/StatsAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/StatsAPI.java index 0bf0b6e576..a1f9b3c7cf 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/StatsAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/StatsAPI.java @@ -24,13 +24,9 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @@ -46,9 +42,6 @@ public class StatsAPI { @Autowired private StatsService statsService; - @Autowired - private WebResponseExceptionTranslator providerExceptionHandler; - @RequestMapping(value = "summary", produces = MediaType.APPLICATION_JSON_VALUE) public String statsSummary(ModelMap m) { @@ -80,9 +73,4 @@ public String statsByClientId(@PathVariable("id") Long id, ModelMap m) { return JsonEntityView.VIEWNAME; } - @ExceptionHandler(OAuth2Exception.class) - public ResponseEntity handleException(Exception e) throws Exception { - logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); - return providerExceptionHandler.translate(e); - } } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/UserInfoEndpoint.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/UserInfoEndpoint.java index 4aa6e8d061..c3cf642b22 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/UserInfoEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/UserInfoEndpoint.java @@ -32,14 +32,10 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -65,9 +61,6 @@ public class UserInfoEndpoint { @Autowired private ClientDetailsEntityService clientService; - @Autowired - private WebResponseExceptionTranslator providerExceptionHandler; - /** * Logger for this class */ @@ -146,9 +139,4 @@ public String getInfo(@RequestParam(value="claims", required=false) String claim } - @ExceptionHandler(OAuth2Exception.class) - public ResponseEntity handleException(Exception e) throws Exception { - logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); - return providerExceptionHandler.translate(e); - } } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/WhitelistAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/WhitelistAPI.java index 5f3272171b..e951b03e03 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/WhitelistAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/WhitelistAPI.java @@ -32,13 +32,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; -import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -68,9 +64,6 @@ public class WhitelistAPI { */ private static final Logger logger = LoggerFactory.getLogger(WhitelistAPI.class); - @Autowired - private WebResponseExceptionTranslator providerExceptionHandler; - private Gson gson = new Gson(); private JsonParser parser = new JsonParser(); @@ -215,9 +208,4 @@ public String getWhitelistedSite(@PathVariable("id") Long id, ModelMap m) { } - @ExceptionHandler(OAuth2Exception.class) - public ResponseEntity handleException(Exception e) throws Exception { - logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); - return providerExceptionHandler.translate(e); - } } diff --git a/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java index 1accdecec1..92480140cb 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java @@ -97,9 +97,6 @@ public class AuthorizationRequestEndpoint { @Autowired private OIDCTokenService oidcTokenService; - @Autowired - private WebResponseExceptionTranslator providerExceptionHandler; - @Autowired private ClaimsProcessingService claimsProcessingService; @@ -225,12 +222,4 @@ public String authorizationRequest(@RequestBody String jsonString, Model m, Auth } - - - @ExceptionHandler(OAuth2Exception.class) - public ResponseEntity handleException(Exception e) throws Exception { - logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); - return providerExceptionHandler.translate(e); - } - } diff --git a/uma-server/src/main/java/org/mitre/uma/web/PermissionRegistrationEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/PermissionRegistrationEndpoint.java index 6a7c360368..e63fd78585 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/PermissionRegistrationEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/PermissionRegistrationEndpoint.java @@ -76,9 +76,6 @@ public class PermissionRegistrationEndpoint { @Autowired private SystemScopeService scopeService; - @Autowired - private WebResponseExceptionTranslator providerExceptionHandler; - private JsonParser parser = new JsonParser(); @RequestMapping(method = RequestMethod.POST, consumes = MimeTypeUtils.APPLICATION_JSON_VALUE, produces = MimeTypeUtils.APPLICATION_JSON_VALUE) @@ -161,11 +158,4 @@ public String getPermissionTicket(@RequestBody String jsonString, Model m, Authe } - - @ExceptionHandler(OAuth2Exception.class) - public ResponseEntity handleException(Exception e) throws Exception { - logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); - return providerExceptionHandler.translate(e); - } - } diff --git a/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java index 75f33f1877..9141701405 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java @@ -81,10 +81,6 @@ public class ResourceSetRegistrationEndpoint { @Autowired private SystemScopeService scopeService; - @Autowired - private WebResponseExceptionTranslator providerExceptionHandler; - - private JsonParser parser = new JsonParser(); @RequestMapping(method = RequestMethod.POST, produces = MimeTypeUtils.APPLICATION_JSON_VALUE, consumes = MimeTypeUtils.APPLICATION_JSON_VALUE) @@ -323,11 +319,4 @@ private ResourceSet validateScopes(ResourceSet rs) { return rs; } - @ExceptionHandler(OAuth2Exception.class) - public ResponseEntity handleException(Exception e) throws Exception { - logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage()); - return providerExceptionHandler.translate(e); - } - - } From 8359ac28132b58ded8b4a1292e0ceb65ca8d0b0c Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Thu, 25 Jun 2015 11:55:58 -0400 Subject: [PATCH 005/465] fixed refresh token lookup --- .../repository/impl/JpaOAuth2TokenRepository.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java index 3127e39d44..fa64ce53e5 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java @@ -105,9 +105,14 @@ public void clearAccessTokensForRefreshToken(OAuth2RefreshTokenEntity refreshTok @Override public OAuth2RefreshTokenEntity getRefreshTokenByValue(String refreshTokenValue) { - TypedQuery query = manager.createNamedQuery(OAuth2RefreshTokenEntity.QUERY_BY_TOKEN_VALUE, OAuth2RefreshTokenEntity.class); - query.setParameter(OAuth2RefreshTokenEntity.PARAM_TOKEN_VALUE, refreshTokenValue); - return JpaUtil.getSingleResult(query.getResultList()); + try { + JWT jwt = JWTParser.parse(refreshTokenValue); + TypedQuery query = manager.createNamedQuery(OAuth2RefreshTokenEntity.QUERY_BY_TOKEN_VALUE, OAuth2RefreshTokenEntity.class); + query.setParameter(OAuth2RefreshTokenEntity.PARAM_TOKEN_VALUE, jwt); + return JpaUtil.getSingleResult(query.getResultList()); + } catch (ParseException e) { + return null; + } } @Override From 2f4d9ce54b4daf6eb0a49c2481b38484dcc824a3 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Thu, 25 Jun 2015 12:07:38 -0400 Subject: [PATCH 006/465] clearing out refresh tokens is now configurable, closes #409 --- .../mitre/oauth2/model/ClientDetailsEntity.java | 17 +++++++++++++++++ .../db/tables/hsql_database_tables.sql | 3 ++- .../src/main/webapp/resources/js/client.js | 4 +++- .../webapp/resources/js/locale/en/messages.json | 1 + .../main/webapp/resources/template/client.html | 4 ++++ .../impl/DefaultOAuth2ProviderTokenService.java | 5 +++-- 6 files changed, 30 insertions(+), 4 deletions(-) diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/ClientDetailsEntity.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/ClientDetailsEntity.java index 144d3c24c5..e5634086e7 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/ClientDetailsEntity.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/ClientDetailsEntity.java @@ -140,6 +140,7 @@ public class ClientDetailsEntity implements ClientDetails { private boolean allowIntrospection = false; // do we let this client call the introspection endpoint? private Integer idTokenValiditySeconds; //timeout for id tokens private Date createdAt; // time the client was created + private boolean clearAccessTokensOnRefresh = true; // do we clear access tokens on refresh? public enum AuthMethod { SECRET_POST("client_secret_post"), @@ -947,5 +948,21 @@ public void setCreatedAt(Date createdAt) { public boolean isAutoApprove(String scope) { return false; } + + /** + * @return the clearAccessTokensOnRefresh + */ + @Basic + @Column(name = "clear_access_tokens_on_refresh") + public boolean isClearAccessTokensOnRefresh() { + return clearAccessTokensOnRefresh; + } + + /** + * @param clearAccessTokensOnRefresh the clearAccessTokensOnRefresh to set + */ + public void setClearAccessTokensOnRefresh(boolean clearAccessTokensOnRefresh) { + this.clearAccessTokensOnRefresh = clearAccessTokensOnRefresh; + } } diff --git a/openid-connect-server-webapp/src/main/resources/db/tables/hsql_database_tables.sql b/openid-connect-server-webapp/src/main/resources/db/tables/hsql_database_tables.sql index 2e4d68e109..ff91c3990f 100644 --- a/openid-connect-server-webapp/src/main/resources/db/tables/hsql_database_tables.sql +++ b/openid-connect-server-webapp/src/main/resources/db/tables/hsql_database_tables.sql @@ -167,7 +167,8 @@ CREATE TABLE IF NOT EXISTS client_details ( require_auth_time BOOLEAN, created_at TIMESTAMP, initiate_login_uri VARCHAR(2048), - post_logout_redirect_uri VARCHAR(2048), + clear_access_tokens_on_refresh BOOLEAN DEFAULT true NOT NULL, + UNIQUE (client_id) ); diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/client.js b/openid-connect-server-webapp/src/main/webapp/resources/js/client.js index ed9b0d601c..a892d52078 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/client.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/client.js @@ -85,10 +85,11 @@ var ClientModel = Backbone.Model.extend({ clientDescription:"", reuseRefreshToken:true, + clearAccessTokensOnRefresh:true, dynamicallyRegistered:false, allowIntrospection:false, idTokenValiditySeconds: null, - createdAt:null, + createdAt:null, allowRefresh:false, displayClientSecret: false, @@ -966,6 +967,7 @@ var ClientFormView = Backbone.View.extend({ initiateLoginUri: $('#initiateLoginUri input').val(), postLogoutRedirectUris: this.postLogoutRedirectUrisCollection.pluck('item'), reuseRefreshToken: $('#reuseRefreshToken').is(':checked'), + clearAccessTokensOnRefresh: $('#clearAccessTokensOnRefresh').is(':checked'), requireAuthTime: $('#requireAuthTime input').is(':checked'), defaultMaxAge: parseInt($('#defaultMaxAge input').val()), contacts: this.contactsCollection.pluck('item'), diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json b/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json index 98d51067e1..90823c198e 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json @@ -108,6 +108,7 @@ "refresh-tokens-issued": "Refresh tokens are issued for this client", "refresh-tokens-issued-help": "This will add the offline_access scope to the client's scopes.", "refresh-tokens-reused": "Refresh tokens for this client are re-used", + "clear-access-tokens": "Active access tokens are automatically revoked when the refresh token is used", "refresh-tokens-no-expire": "Refresh tokens do not time out", "registered": "Registered at", "registration-token": "Registration Token:", diff --git a/openid-connect-server-webapp/src/main/webapp/resources/template/client.html b/openid-connect-server-webapp/src/main/webapp/resources/template/client.html index 2f3386ed4d..6a61f38c44 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/template/client.html +++ b/openid-connect-server-webapp/src/main/webapp/resources/template/client.html @@ -570,6 +570,10 @@

+ > + +
+
/>
diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java index c77e24a704..d93420717c 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java @@ -261,8 +261,9 @@ public OAuth2AccessTokenEntity refreshAccessToken(String refreshTokenValue, Toke } // clear out any access tokens - // TODO: make this a configurable option - tokenRepository.clearAccessTokensForRefreshToken(refreshToken); + if (client.isClearAccessTokensOnRefresh()) { + tokenRepository.clearAccessTokensForRefreshToken(refreshToken); + } if (refreshToken.isExpired()) { tokenRepository.removeRefreshToken(refreshToken); From 50cbeb3e4c42a19a5eecf93ccb72fb8b1162753c Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Thu, 25 Jun 2015 12:11:31 -0400 Subject: [PATCH 007/465] DB table sync --- .../src/main/resources/db/tables/mysql_database_tables.sql | 3 ++- .../src/main/resources/db/tables/psql_database_tables.sql | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/openid-connect-server-webapp/src/main/resources/db/tables/mysql_database_tables.sql b/openid-connect-server-webapp/src/main/resources/db/tables/mysql_database_tables.sql index bab0200004..62f3badc5b 100644 --- a/openid-connect-server-webapp/src/main/resources/db/tables/mysql_database_tables.sql +++ b/openid-connect-server-webapp/src/main/resources/db/tables/mysql_database_tables.sql @@ -167,7 +167,8 @@ CREATE TABLE IF NOT EXISTS client_details ( require_auth_time BOOLEAN, created_at TIMESTAMP NULL, initiate_login_uri VARCHAR(2048), - post_logout_redirect_uri VARCHAR(2048), + clear_access_tokens_on_refresh BOOLEAN DEFAULT true NOT NULL, + UNIQUE (client_id) ); diff --git a/openid-connect-server-webapp/src/main/resources/db/tables/psql_database_tables.sql b/openid-connect-server-webapp/src/main/resources/db/tables/psql_database_tables.sql index a793bb7cbf..92818854ba 100644 --- a/openid-connect-server-webapp/src/main/resources/db/tables/psql_database_tables.sql +++ b/openid-connect-server-webapp/src/main/resources/db/tables/psql_database_tables.sql @@ -167,7 +167,8 @@ CREATE TABLE IF NOT EXISTS client_details ( require_auth_time BOOLEAN, created_at TIMESTAMP, initiate_login_uri VARCHAR(2048), - post_logout_redirect_uri VARCHAR(2048), + clear_access_tokens_on_refresh BOOLEAN DEFAULT true NOT NULL, + UNIQUE (client_id) ); From d9efeb3b677b27ec6be28138e6f763ebc138eb34 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Thu, 25 Jun 2015 12:40:28 -0400 Subject: [PATCH 008/465] added clear access tokens to export/import --- .../openid/connect/service/impl/MITREidDataService_1_2.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_2.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_2.java index 6815ea4760..59633444bb 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_2.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_2.java @@ -429,6 +429,7 @@ private void writeClients(JsonWriter writer) { writer.name("description").value(client.getClientDescription()); writer.name("allowIntrospection").value(client.isAllowIntrospection()); writer.name("reuseRefreshToken").value(client.isReuseRefreshToken()); + writer.name("clearAccessTokensOnRefresh").value(client.isClearAccessTokensOnRefresh()); writer.name("dynamicallyRegistered").value(client.isDynamicallyRegistered()); writer.endObject(); logger.debug("Wrote client {}", client.getId()); @@ -1057,6 +1058,8 @@ private void readClients(JsonReader reader) throws IOException { client.setAllowIntrospection(reader.nextBoolean()); } else if (name.equals("reuseRefreshToken")) { client.setReuseRefreshToken(reader.nextBoolean()); + } else if (name.equals("clearAccessTokensOnRefresh")) { + client.setClearAccessTokensOnRefresh(reader.nextBoolean()); } else if (name.equals("dynamicallyRegistered")) { client.setDynamicallyRegistered(reader.nextBoolean()); } else { From c4aaa29ffc37aa2aa28722efa3db932eb7078573 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Thu, 25 Jun 2015 12:44:52 -0400 Subject: [PATCH 009/465] updated unit tests for new refresh token mode --- ...TestDefaultOAuth2ProviderTokenService.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultOAuth2ProviderTokenService.java b/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultOAuth2ProviderTokenService.java index ad649dedf4..9e16b44318 100644 --- a/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultOAuth2ProviderTokenService.java +++ b/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultOAuth2ProviderTokenService.java @@ -57,6 +57,7 @@ import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.when; import static org.junit.Assert.assertThat; @@ -128,6 +129,9 @@ public void prepare() { // by default in tests, allow refresh tokens Mockito.when(client.isAllowRefresh()).thenReturn(true); + + // by default, clear access tokens on refresh + Mockito.when(client.isClearAccessTokensOnRefresh()).thenReturn(true); badClient = Mockito.mock(ClientDetailsEntity.class); Mockito.when(badClient.getClientId()).thenReturn(badClientId); @@ -419,6 +423,25 @@ public void refreshAccessToken_rotateRefreshToken() { } + @Test + public void refreshAccessToken_keepAccessTokens() { + + when(client.isClearAccessTokensOnRefresh()).thenReturn(false); + + OAuth2AccessTokenEntity token = service.refreshAccessToken(refreshTokenValue, tokenRequest); + + Mockito.verify(tokenRepository, never()).clearAccessTokensForRefreshToken(refreshToken); + + assertThat(token.getClient(), equalTo(client)); + assertThat(token.getRefreshToken(), equalTo(refreshToken)); + assertThat(token.getAuthenticationHolder(), equalTo(storedAuthHolder)); + + Mockito.verify(tokenEnhancer).enhance(token, storedAuthentication); + Mockito.verify(tokenRepository).saveAccessToken(token); + Mockito.verify(scopeService, Mockito.atLeastOnce()).removeReservedScopes(Matchers.anySet()); + + } + @Test public void refreshAccessToken_requestingSameScope() { From 13239c17541948dd7c595ac070aa5723000e1db0 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 26 Jun 2015 15:24:45 -0400 Subject: [PATCH 010/465] make eclipse happy with the warpath plugin --- uma-server-webapp/pom.xml | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/uma-server-webapp/pom.xml b/uma-server-webapp/pom.xml index e4ccf27d8e..a34d8aa499 100644 --- a/uma-server-webapp/pom.xml +++ b/uma-server-webapp/pom.xml @@ -62,6 +62,41 @@ + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + + org.appfuse.plugins + + + warpath-maven-plugin + + + [3.5.0,) + + + add-classes + + + + + + + + + + + + From cd47d32e2d124e13b09456e24aaebf7e650ae420 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 26 Jun 2015 15:44:12 -0400 Subject: [PATCH 011/465] split required claim sets out as separate indirection structure, closes #813 --- .../org/mitre/uma/model/PermissionTicket.java | 7 +- .../org/mitre/uma/model/RequiredClaimSet.java | 108 ++++++++++++++++++ .../java/org/mitre/uma/model/ResourceSet.java | 10 +- .../uma/service/ClaimsProcessingService.java | 3 +- .../db/tables/hsql_database_tables.sql | 22 +++- .../service/impl/MatchAllClaimsProcessor.java | 24 +++- .../uma/web/AuthorizationRequestEndpoint.java | 4 +- .../java/org/mitre/uma/web/ClaimsAPI.java | 16 ++- 8 files changed, 177 insertions(+), 17 deletions(-) create mode 100644 openid-connect-common/src/main/java/org/mitre/uma/model/RequiredClaimSet.java diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/PermissionTicket.java b/openid-connect-common/src/main/java/org/mitre/uma/model/PermissionTicket.java index eb9ac782b4..68c2681f47 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/PermissionTicket.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/PermissionTicket.java @@ -29,6 +29,7 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.OneToMany; @@ -130,7 +131,11 @@ public void setExpiration(Date expiration) { * @return the claimsSupplied */ @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) - @JoinColumn(name = "permission_ticket_id") + @JoinTable( + name = "claim_to_permission_ticket", + joinColumns = @JoinColumn(name = "permission_ticket_id"), + inverseJoinColumns = @JoinColumn(name = "claim_id") + ) public Collection getClaimsSupplied() { return claimsSupplied; } diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/RequiredClaimSet.java b/openid-connect-common/src/main/java/org/mitre/uma/model/RequiredClaimSet.java new file mode 100644 index 0000000000..e00f278f3c --- /dev/null +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/RequiredClaimSet.java @@ -0,0 +1,108 @@ +/******************************************************************************* + * Copyright 2015 The MITRE Corporation + * and the MIT Kerberos and Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +package org.mitre.uma.model; + +import java.util.Collection; +import java.util.Set; + +import javax.persistence.CascadeType; +import javax.persistence.CollectionTable; +import javax.persistence.Column; +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.OneToMany; +import javax.persistence.Table; + +/** + * A set of claims required to fulfill a given permission. + * + * @author jricher + * + */ +@Entity +@Table(name = "required_claim_set") +public class RequiredClaimSet { + + private Long id; + private Collection claimsRequired; + private Set scopes; + + /** + * @return the id + */ + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + public Long getId() { + return id; + } + + /** + * @param id the id to set + */ + public void setId(Long id) { + this.id = id; + } + + /** + * @return the claimsRequired + */ + @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @JoinTable( + name = "claim_to_permission_ticket", + joinColumns = @JoinColumn(name = "permission_ticket_id"), + inverseJoinColumns = @JoinColumn(name = "claim_id") + ) + public Collection getClaimsRequired() { + return claimsRequired; + } + + /** + * @param claimsRequired the claimsRequired to set + */ + public void setClaimsRequired(Collection claimsRequired) { + this.claimsRequired = claimsRequired; + } + + /** + * @return the scopes + */ + @ElementCollection(fetch = FetchType.EAGER) + @Column(name = "scope") + @CollectionTable( + name = "resource_set_scope", + joinColumns = @JoinColumn(name = "owner_id") + ) + public Set getScopes() { + return scopes; + } + + /** + * @param scopes the scopes to set + */ + public void setScopes(Set scopes) { + this.scopes = scopes; + } + +} diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/ResourceSet.java b/openid-connect-common/src/main/java/org/mitre/uma/model/ResourceSet.java index f577e0fe6d..8b4ca00aaf 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/ResourceSet.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/ResourceSet.java @@ -59,7 +59,7 @@ public class ResourceSet { private String owner; // username of the person responsible for the registration (either directly or via OAuth token) private String clientId; // client id of the protected resource that registered this resource set via OAuth token - private Collection claimsRequired; + private Collection requiredClaimSets; /** * @return the id @@ -199,15 +199,15 @@ public void setClientId(String clientId) { */ @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) @JoinColumn(name = "resource_set_id") - public Collection getClaimsRequired() { - return claimsRequired; + public Collection getRequiredClaimSets() { + return requiredClaimSets; } /** * @param claimsRequired the claimsRequired to set */ - public void setClaimsRequired(Collection claimsRequired) { - this.claimsRequired = claimsRequired; + public void setRequiredClaimSets(Collection claimsRequired) { + this.requiredClaimSets = claimsRequired; } diff --git a/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java b/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java index 18c531fab2..0130f673f0 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java @@ -20,6 +20,7 @@ import java.util.Collection; import org.mitre.uma.model.Claim; +import org.mitre.uma.model.RequiredClaimSet; /** * @@ -40,6 +41,6 @@ public interface ClaimsProcessingService { * @param claimsSupplied the supplied claims to test * @return the unmatched claims (if any), an empty set if the claims are satisfied, never null */ - public Collection claimsAreSatisfied(Collection claimsRequired, Collection claimsSupplied); + public Collection claimsAreSatisfied(Collection claimsRequired, Collection claimsSupplied); } diff --git a/openid-connect-server-webapp/src/main/resources/db/tables/hsql_database_tables.sql b/openid-connect-server-webapp/src/main/resources/db/tables/hsql_database_tables.sql index ff91c3990f..87cae376a7 100644 --- a/openid-connect-server-webapp/src/main/resources/db/tables/hsql_database_tables.sql +++ b/openid-connect-server-webapp/src/main/resources/db/tables/hsql_database_tables.sql @@ -313,8 +313,26 @@ CREATE TABLE IF NOT EXISTS claim ( friendly_name VARCHAR(1024), claim_type VARCHAR(1024), claim_value VARCHAR(1024), - resource_set_id BIGINT, - permission_ticket_id BIGINT +); + +CREATE TABLE IF NOT EXISTS claim_to_claim_set ( + required_claim_set_id BIGINT NOT NULL, + claim_id BIGINT NOT NULL +); + +CREATE TABLE IF NOT EXISTS claim_to_permission_ticket ( + permission_ticket_id BIGINT NOT NULL, + claim_id BIGINT NOT NULL +); + +CREATE TABLE IF NOT EXISTS required_claim_set ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) PRIMARY KEY, + resource_set_id BIGINT NOT NULL +); + +CREATE TABLE IF NOT EXISTS required_claim_set_scope ( + owner_id BIGINT NOT NULL, + scope VARCHAR(256) NOT NULL ); CREATE TABLE IF NOT EXISTS claim_token_format ( diff --git a/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsProcessor.java b/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsProcessor.java index 3455279de4..54106cb5e4 100644 --- a/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsProcessor.java +++ b/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsProcessor.java @@ -21,6 +21,7 @@ import java.util.HashSet; import org.mitre.uma.model.Claim; +import org.mitre.uma.model.RequiredClaimSet; import org.mitre.uma.service.ClaimsProcessingService; import org.springframework.stereotype.Service; @@ -34,8 +35,27 @@ @Service("matchAllClaimsProcessor") public class MatchAllClaimsProcessor implements ClaimsProcessingService { + /* (non-Javadoc) + * @see org.mitre.uma.service.ClaimsProcessingService#claimsAreSatisfied(java.util.Collection, java.util.Collection) + */ @Override - public Collection claimsAreSatisfied(Collection claimsRequired, Collection claimsSupplied) { + public Collection claimsAreSatisfied(Collection claimsRequired, Collection claimsSupplied) { + Collection allUnmatched = new HashSet<>(); + for (RequiredClaimSet requiredClaimSet : claimsRequired) { + Collection unmatched = checkIndividualClaims(requiredClaimSet.getClaimsRequired(), claimsSupplied); + if (unmatched.isEmpty()) { + // we found something that's satisfied the claims, let's go with it! + return unmatched; + } else { + allUnmatched.addAll(unmatched); + } + } + + // otherwise, tell the caller that we'll need some set of these fulfilled somehow + return allUnmatched; + } + + private Collection checkIndividualClaims(Collection claimsRequired, Collection claimsSupplied) { Collection claimsUnmatched = new HashSet<>(claimsRequired); @@ -62,5 +82,5 @@ public Collection claimsAreSatisfied(Collection claimsRequired, Co return claimsUnmatched; } - + } diff --git a/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java index 92480140cb..dd4b4f91c4 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java @@ -131,7 +131,7 @@ public String authorizationRequest(@RequestBody String jsonString, Model m, Auth ResourceSet rs = ticket.getPermission().getResourceSet(); - if (rs.getClaimsRequired() == null || rs.getClaimsRequired().isEmpty()) { + if (rs.getRequiredClaimSets() == null || rs.getRequiredClaimSets().isEmpty()) { // the required claims are empty, this resource has no way to be authorized m.addAttribute(JsonErrorView.ERROR, "not_authorized"); @@ -141,7 +141,7 @@ public String authorizationRequest(@RequestBody String jsonString, Model m, Auth } else { // claims weren't empty or missing, we need to check against what we have - Collection claimsUnmatched = claimsProcessingService.claimsAreSatisfied(rs.getClaimsRequired(), ticket.getClaimsSupplied()); + Collection claimsUnmatched = claimsProcessingService.claimsAreSatisfied(rs.getRequiredClaimSets(), ticket.getClaimsSupplied()); if (claimsUnmatched.isEmpty()) { // if the unmatched claims come back empty, by function contract that means we're happy and can issue a token diff --git a/uma-server/src/main/java/org/mitre/uma/web/ClaimsAPI.java b/uma-server/src/main/java/org/mitre/uma/web/ClaimsAPI.java index caeac27616..b8d4692b3c 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/ClaimsAPI.java +++ b/uma-server/src/main/java/org/mitre/uma/web/ClaimsAPI.java @@ -26,6 +26,7 @@ import org.mitre.openid.connect.view.JsonErrorView; import org.mitre.openid.connect.web.RootController; import org.mitre.uma.model.Claim; +import org.mitre.uma.model.RequiredClaimSet; import org.mitre.uma.model.ResourceSet; import org.mitre.uma.service.ResourceSetService; import org.slf4j.Logger; @@ -56,6 +57,13 @@ @RequestMapping("/" + ClaimsAPI.URL) @PreAuthorize("hasRole('ROLE_USER')") public class ClaimsAPI { + + // + // + // FIXME + // + // + // Logger for this class private static final Logger logger = LoggerFactory.getLogger(ClaimsAPI.class); @@ -90,7 +98,7 @@ public String getClaimsForResourceSet(@PathVariable (value = "rsid") Long rsid, return HttpCodeView.VIEWNAME; } - m.addAttribute(JsonEntityView.ENTITY, rs.getClaimsRequired()); + m.addAttribute(JsonEntityView.ENTITY, rs.getRequiredClaimSets()); return JsonEntityView.VIEWNAME; } @@ -114,11 +122,11 @@ public String setClaimsForResourceSet(@PathVariable (value = "rsid") Long rsid, @SuppressWarnings("serial") Set claims = (new Gson()).fromJson(jsonString, new TypeToken>() {}.getType()); - rs.setClaimsRequired(claims); - + //rs.setClaimsRequired(claims); + resourceSetService.update(rs, rs); - m.addAttribute(JsonEntityView.ENTITY, rs.getClaimsRequired()); + m.addAttribute(JsonEntityView.ENTITY, rs.getRequiredClaimSets()); return JsonEntityView.VIEWNAME; } From 667c76627317d918ad779b651ebff555d060b603 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 26 Jun 2015 17:17:38 -0400 Subject: [PATCH 012/465] reverted over-reaching check on webfinger fetcher --- .../service/impl/WebfingerIssuerService.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/WebfingerIssuerService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/WebfingerIssuerService.java index 55ddd55300..31a4ed36c6 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/WebfingerIssuerService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/WebfingerIssuerService.java @@ -208,14 +208,12 @@ public String load(UriComponents key) throws Exception { // preserving http scheme is strictly for demo system use only. String scheme = key.getScheme(); - if (!Strings.isNullOrEmpty(scheme)) { - if (scheme.equals("http")) { - if (forceHttps) { - throw new IllegalArgumentException("Scheme must start with htps"); - } else { - logger.warn("Webfinger endpoint MUST use the https URI scheme, overriding by configuration"); - scheme = "http://"; // add on colon and slashes. - } + if (!Strings.isNullOrEmpty(scheme) &&scheme.equals("http")) { + if (forceHttps) { + throw new IllegalArgumentException("Scheme must start with htps"); + } else { + logger.warn("Webfinger endpoint MUST use the https URI scheme, overriding by configuration"); + scheme = "http://"; // add on colon and slashes. } } else { scheme = "https://"; From b8a54869953080a2b516363647bbdb1e2517e40d Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 26 Jun 2015 17:17:51 -0400 Subject: [PATCH 013/465] made required claims sets stick in the database --- .../org/mitre/uma/model/RequiredClaimSet.java | 22 ++++++++++- .../db/tables/hsql_database_tables.sql | 3 +- .../service/impl/MatchAllClaimsProcessor.java | 1 + .../web/PermissionRegistrationEndpoint.java | 2 +- .../web/ResourceSetRegistrationEndpoint.java | 37 ++++++++++++++++--- 5 files changed, 56 insertions(+), 9 deletions(-) diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/RequiredClaimSet.java b/openid-connect-common/src/main/java/org/mitre/uma/model/RequiredClaimSet.java index e00f278f3c..8553c79584 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/RequiredClaimSet.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/RequiredClaimSet.java @@ -20,6 +20,7 @@ import java.util.Collection; import java.util.Set; +import javax.persistence.Basic; import javax.persistence.CascadeType; import javax.persistence.CollectionTable; import javax.persistence.Column; @@ -45,6 +46,7 @@ public class RequiredClaimSet { private Long id; + private String name; private Collection claimsRequired; private Set scopes; @@ -65,13 +67,29 @@ public void setId(Long id) { this.id = id; } + /** + * @return the name + */ + @Basic + @Column(name = "name") + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + /** * @return the claimsRequired */ @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) @JoinTable( - name = "claim_to_permission_ticket", - joinColumns = @JoinColumn(name = "permission_ticket_id"), + name = "claim_to_claim_set", + joinColumns = @JoinColumn(name = "required_claim_set_id"), inverseJoinColumns = @JoinColumn(name = "claim_id") ) public Collection getClaimsRequired() { diff --git a/openid-connect-server-webapp/src/main/resources/db/tables/hsql_database_tables.sql b/openid-connect-server-webapp/src/main/resources/db/tables/hsql_database_tables.sql index 87cae376a7..0efd362959 100644 --- a/openid-connect-server-webapp/src/main/resources/db/tables/hsql_database_tables.sql +++ b/openid-connect-server-webapp/src/main/resources/db/tables/hsql_database_tables.sql @@ -327,7 +327,8 @@ CREATE TABLE IF NOT EXISTS claim_to_permission_ticket ( CREATE TABLE IF NOT EXISTS required_claim_set ( id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) PRIMARY KEY, - resource_set_id BIGINT NOT NULL + name VARCHAR(1024), + resource_set_id BIGINT ); CREATE TABLE IF NOT EXISTS required_claim_set_scope ( diff --git a/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsProcessor.java b/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsProcessor.java index 54106cb5e4..f640ed9c6d 100644 --- a/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsProcessor.java +++ b/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsProcessor.java @@ -47,6 +47,7 @@ public Collection claimsAreSatisfied(Collection claimsR // we found something that's satisfied the claims, let's go with it! return unmatched; } else { + // otherwise add it to the stack to send back allUnmatched.addAll(unmatched); } } diff --git a/uma-server/src/main/java/org/mitre/uma/web/PermissionRegistrationEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/PermissionRegistrationEndpoint.java index e63fd78585..456a4add07 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/PermissionRegistrationEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/PermissionRegistrationEndpoint.java @@ -97,7 +97,7 @@ public String getPermissionTicket(@RequestBody String jsonString, Model m, Authe if (rsid == null || scopes == null || scopes.isEmpty()){ // missing information m.addAttribute("code", HttpStatus.BAD_REQUEST); - m.addAttribute("errorMessage", "Missing required component of resource registration request."); + m.addAttribute("errorMessage", "Missing required component of permission registration request."); return JsonErrorView.VIEWNAME; } diff --git a/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java index 9141701405..584abecf3b 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java @@ -28,6 +28,8 @@ import org.mitre.openid.connect.view.HttpCodeView; import org.mitre.openid.connect.view.JsonEntityView; import org.mitre.openid.connect.view.JsonErrorView; +import org.mitre.uma.model.Claim; +import org.mitre.uma.model.RequiredClaimSet; import org.mitre.uma.model.ResourceSet; import org.mitre.uma.service.ResourceSetService; import org.mitre.uma.view.ResourceSetEntityAbbreviatedView; @@ -36,22 +38,19 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.util.MimeTypeUtils; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.google.common.base.Strings; +import com.google.common.collect.Sets; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; @@ -121,7 +120,35 @@ public String createResourceSet(@RequestBody String jsonString, Model m, Authent m.addAttribute(JsonErrorView.ERROR_MESSAGE, "Resource request was missing one or more required fields."); return JsonErrorView.VIEWNAME; } - + + //// + //// TEMP + //// + + Set claims = new HashSet<>(); + Claim e = new Claim(); + e.setIssuer(Sets.newHashSet("https://healthauth.org/")); + e.setName("email"); + e.setValue("alice@healthauth.org"); + claims.add(e); + + /* TODO: claims need to be multi-typed + Claim ev = new Claim(); + ev.setIssuer(Sets.newHashSet("https://healthauth.org/")); + e.setName("email_verified"); + ev.setValue(true); + claims.add(e); + */ + RequiredClaimSet reqired = new RequiredClaimSet(); + reqired.setScopes(rs.getScopes()); + reqired.setClaimsRequired(claims); + + rs.setRequiredClaimSets(Sets.newHashSet(reqired)); + //// + //// END TEMP + //// + + ResourceSet saved = resourceSetService.saveNew(rs); m.addAttribute(HttpCodeView.CODE, HttpStatus.CREATED); From 2cfaa1c1d7b66850d710f8ef970caf9b6cdebb8b Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 29 Jun 2015 11:15:45 -0400 Subject: [PATCH 014/465] renamed RequiredClaimSet to Policy --- .../uma/model/{RequiredClaimSet.java => Policy.java} | 10 +++++----- .../main/java/org/mitre/uma/model/ResourceSet.java | 12 ++++++------ .../mitre/uma/service/ClaimsProcessingService.java | 4 ++-- .../resources/db/tables/hsql_database_tables.sql | 8 ++++---- .../uma/service/impl/MatchAllClaimsProcessor.java | 8 ++++---- .../mitre/uma/web/AuthorizationRequestEndpoint.java | 6 ++++-- .../src/main/java/org/mitre/uma/web/ClaimsAPI.java | 6 +++--- .../uma/web/ResourceSetRegistrationEndpoint.java | 6 +++--- 8 files changed, 31 insertions(+), 29 deletions(-) rename openid-connect-common/src/main/java/org/mitre/uma/model/{RequiredClaimSet.java => Policy.java} (93%) diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/RequiredClaimSet.java b/openid-connect-common/src/main/java/org/mitre/uma/model/Policy.java similarity index 93% rename from openid-connect-common/src/main/java/org/mitre/uma/model/RequiredClaimSet.java rename to openid-connect-common/src/main/java/org/mitre/uma/model/Policy.java index 8553c79584..286fb578a4 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/RequiredClaimSet.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/Policy.java @@ -42,8 +42,8 @@ * */ @Entity -@Table(name = "required_claim_set") -public class RequiredClaimSet { +@Table(name = "policy") +public class Policy { private Long id; private String name; @@ -88,8 +88,8 @@ public void setName(String name) { */ @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) @JoinTable( - name = "claim_to_claim_set", - joinColumns = @JoinColumn(name = "required_claim_set_id"), + name = "claim_to_policy", + joinColumns = @JoinColumn(name = "policy_id"), inverseJoinColumns = @JoinColumn(name = "claim_id") ) public Collection getClaimsRequired() { @@ -109,7 +109,7 @@ public void setClaimsRequired(Collection claimsRequired) { @ElementCollection(fetch = FetchType.EAGER) @Column(name = "scope") @CollectionTable( - name = "resource_set_scope", + name = "policy_scope", joinColumns = @JoinColumn(name = "owner_id") ) public Set getScopes() { diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/ResourceSet.java b/openid-connect-common/src/main/java/org/mitre/uma/model/ResourceSet.java index 8b4ca00aaf..bb4c680367 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/ResourceSet.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/ResourceSet.java @@ -59,7 +59,7 @@ public class ResourceSet { private String owner; // username of the person responsible for the registration (either directly or via OAuth token) private String clientId; // client id of the protected resource that registered this resource set via OAuth token - private Collection requiredClaimSets; + private Collection policies; /** * @return the id @@ -199,15 +199,15 @@ public void setClientId(String clientId) { */ @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) @JoinColumn(name = "resource_set_id") - public Collection getRequiredClaimSets() { - return requiredClaimSets; + public Collection getPolicies() { + return policies; } /** - * @param claimsRequired the claimsRequired to set + * @param policies the claimsRequired to set */ - public void setRequiredClaimSets(Collection claimsRequired) { - this.requiredClaimSets = claimsRequired; + public void setPolicies(Collection policies) { + this.policies = policies; } diff --git a/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java b/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java index 0130f673f0..dab5223277 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java @@ -20,7 +20,7 @@ import java.util.Collection; import org.mitre.uma.model.Claim; -import org.mitre.uma.model.RequiredClaimSet; +import org.mitre.uma.model.Policy; /** * @@ -41,6 +41,6 @@ public interface ClaimsProcessingService { * @param claimsSupplied the supplied claims to test * @return the unmatched claims (if any), an empty set if the claims are satisfied, never null */ - public Collection claimsAreSatisfied(Collection claimsRequired, Collection claimsSupplied); + public Collection claimsAreSatisfied(Collection claimsRequired, Collection claimsSupplied); } diff --git a/openid-connect-server-webapp/src/main/resources/db/tables/hsql_database_tables.sql b/openid-connect-server-webapp/src/main/resources/db/tables/hsql_database_tables.sql index 0efd362959..6040fcfdae 100644 --- a/openid-connect-server-webapp/src/main/resources/db/tables/hsql_database_tables.sql +++ b/openid-connect-server-webapp/src/main/resources/db/tables/hsql_database_tables.sql @@ -315,8 +315,8 @@ CREATE TABLE IF NOT EXISTS claim ( claim_value VARCHAR(1024), ); -CREATE TABLE IF NOT EXISTS claim_to_claim_set ( - required_claim_set_id BIGINT NOT NULL, +CREATE TABLE IF NOT EXISTS claim_to_policy ( + policy_id BIGINT NOT NULL, claim_id BIGINT NOT NULL ); @@ -325,13 +325,13 @@ CREATE TABLE IF NOT EXISTS claim_to_permission_ticket ( claim_id BIGINT NOT NULL ); -CREATE TABLE IF NOT EXISTS required_claim_set ( +CREATE TABLE IF NOT EXISTS policy ( id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) PRIMARY KEY, name VARCHAR(1024), resource_set_id BIGINT ); -CREATE TABLE IF NOT EXISTS required_claim_set_scope ( +CREATE TABLE IF NOT EXISTS policy_scope ( owner_id BIGINT NOT NULL, scope VARCHAR(256) NOT NULL ); diff --git a/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsProcessor.java b/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsProcessor.java index f640ed9c6d..0ed4e0fadf 100644 --- a/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsProcessor.java +++ b/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsProcessor.java @@ -21,7 +21,7 @@ import java.util.HashSet; import org.mitre.uma.model.Claim; -import org.mitre.uma.model.RequiredClaimSet; +import org.mitre.uma.model.Policy; import org.mitre.uma.service.ClaimsProcessingService; import org.springframework.stereotype.Service; @@ -39,10 +39,10 @@ public class MatchAllClaimsProcessor implements ClaimsProcessingService { * @see org.mitre.uma.service.ClaimsProcessingService#claimsAreSatisfied(java.util.Collection, java.util.Collection) */ @Override - public Collection claimsAreSatisfied(Collection claimsRequired, Collection claimsSupplied) { + public Collection claimsAreSatisfied(Collection claimsRequired, Collection claimsSupplied) { Collection allUnmatched = new HashSet<>(); - for (RequiredClaimSet requiredClaimSet : claimsRequired) { - Collection unmatched = checkIndividualClaims(requiredClaimSet.getClaimsRequired(), claimsSupplied); + for (Policy policy : claimsRequired) { + Collection unmatched = checkIndividualClaims(policy.getClaimsRequired(), claimsSupplied); if (unmatched.isEmpty()) { // we found something that's satisfied the claims, let's go with it! return unmatched; diff --git a/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java index dd4b4f91c4..279ae64ac9 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java @@ -131,7 +131,7 @@ public String authorizationRequest(@RequestBody String jsonString, Model m, Auth ResourceSet rs = ticket.getPermission().getResourceSet(); - if (rs.getRequiredClaimSets() == null || rs.getRequiredClaimSets().isEmpty()) { + if (rs.getPolicies() == null || rs.getPolicies().isEmpty()) { // the required claims are empty, this resource has no way to be authorized m.addAttribute(JsonErrorView.ERROR, "not_authorized"); @@ -141,7 +141,9 @@ public String authorizationRequest(@RequestBody String jsonString, Model m, Auth } else { // claims weren't empty or missing, we need to check against what we have - Collection claimsUnmatched = claimsProcessingService.claimsAreSatisfied(rs.getRequiredClaimSets(), ticket.getClaimsSupplied()); + Collection claimsUnmatched = claimsProcessingService.claimsAreSatisfied(rs.getPolicies(), ticket.getClaimsSupplied()); + + // we need to downscope this based on the required set that was matched if it was matched if (claimsUnmatched.isEmpty()) { // if the unmatched claims come back empty, by function contract that means we're happy and can issue a token diff --git a/uma-server/src/main/java/org/mitre/uma/web/ClaimsAPI.java b/uma-server/src/main/java/org/mitre/uma/web/ClaimsAPI.java index b8d4692b3c..f7341b23d1 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/ClaimsAPI.java +++ b/uma-server/src/main/java/org/mitre/uma/web/ClaimsAPI.java @@ -26,7 +26,7 @@ import org.mitre.openid.connect.view.JsonErrorView; import org.mitre.openid.connect.web.RootController; import org.mitre.uma.model.Claim; -import org.mitre.uma.model.RequiredClaimSet; +import org.mitre.uma.model.Policy; import org.mitre.uma.model.ResourceSet; import org.mitre.uma.service.ResourceSetService; import org.slf4j.Logger; @@ -98,7 +98,7 @@ public String getClaimsForResourceSet(@PathVariable (value = "rsid") Long rsid, return HttpCodeView.VIEWNAME; } - m.addAttribute(JsonEntityView.ENTITY, rs.getRequiredClaimSets()); + m.addAttribute(JsonEntityView.ENTITY, rs.getPolicies()); return JsonEntityView.VIEWNAME; } @@ -126,7 +126,7 @@ public String setClaimsForResourceSet(@PathVariable (value = "rsid") Long rsid, resourceSetService.update(rs, rs); - m.addAttribute(JsonEntityView.ENTITY, rs.getRequiredClaimSets()); + m.addAttribute(JsonEntityView.ENTITY, rs.getPolicies()); return JsonEntityView.VIEWNAME; } diff --git a/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java index 584abecf3b..50a04028a4 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java @@ -29,7 +29,7 @@ import org.mitre.openid.connect.view.JsonEntityView; import org.mitre.openid.connect.view.JsonErrorView; import org.mitre.uma.model.Claim; -import org.mitre.uma.model.RequiredClaimSet; +import org.mitre.uma.model.Policy; import org.mitre.uma.model.ResourceSet; import org.mitre.uma.service.ResourceSetService; import org.mitre.uma.view.ResourceSetEntityAbbreviatedView; @@ -139,11 +139,11 @@ public String createResourceSet(@RequestBody String jsonString, Model m, Authent ev.setValue(true); claims.add(e); */ - RequiredClaimSet reqired = new RequiredClaimSet(); + Policy reqired = new Policy(); reqired.setScopes(rs.getScopes()); reqired.setClaimsRequired(claims); - rs.setRequiredClaimSets(Sets.newHashSet(reqired)); + rs.setPolicies(Sets.newHashSet(reqired)); //// //// END TEMP //// From de9f69e4618513929beda43612641fc9e4b24767 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 29 Jun 2015 11:55:27 -0400 Subject: [PATCH 015/465] introduced a claims processor result data shuttle --- .../uma/model/ClaimProcessingResult.java | 96 +++++++++++++++++++ .../uma/service/ClaimsProcessingService.java | 5 +- ...or.java => MatchAllClaimsOnAnyPolicy.java} | 11 ++- .../uma/web/AuthorizationRequestEndpoint.java | 9 +- 4 files changed, 110 insertions(+), 11 deletions(-) create mode 100644 openid-connect-common/src/main/java/org/mitre/uma/model/ClaimProcessingResult.java rename uma-server/src/main/java/org/mitre/uma/service/impl/{MatchAllClaimsProcessor.java => MatchAllClaimsOnAnyPolicy.java} (87%) diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/ClaimProcessingResult.java b/openid-connect-common/src/main/java/org/mitre/uma/model/ClaimProcessingResult.java new file mode 100644 index 0000000000..07f035c7e1 --- /dev/null +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/ClaimProcessingResult.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright 2015 The MITRE Corporation + * and the MIT Kerberos and Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +package org.mitre.uma.model; + +import java.util.Collection; + +/** + * Data shuttle to return results of the claims processing service. + * + * @author jricher + * + */ +public class ClaimProcessingResult { + + private boolean satisfied; + private Collection unmatched; + private Policy matched; + + /** + * Create an unmatched result. isSatisfied is false. + * @param unmatched + */ + public ClaimProcessingResult(Collection unmatched) { + this.satisfied = false; + this.unmatched = unmatched; + this.matched = null; + } + + /** + * Create a matched result. isSatisfied is true. + * @param matched + */ + public ClaimProcessingResult(Policy matched) { + this.satisfied = true; + this.matched = matched; + this.unmatched = null; + } + + /** + * @return the satisfied + */ + public boolean isSatisfied() { + return satisfied; + } + + /** + * @param satisfied the satisfied to set + */ + public void setSatisfied(boolean satisfied) { + this.satisfied = satisfied; + } + + /** + * @return the unmatched + */ + public Collection getUnmatched() { + return unmatched; + } + + /** + * @param unmatched the unmatched to set + */ + public void setUnmatched(Collection unmatched) { + this.unmatched = unmatched; + } + + /** + * @return the matched + */ + public Policy getMatched() { + return matched; + } + + /** + * @param matched the matched to set + */ + public void setMatched(Policy matched) { + this.matched = matched; + } + +} diff --git a/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java b/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java index dab5223277..a0688a43f0 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java @@ -20,6 +20,7 @@ import java.util.Collection; import org.mitre.uma.model.Claim; +import org.mitre.uma.model.ClaimProcessingResult; import org.mitre.uma.model.Policy; /** @@ -39,8 +40,8 @@ public interface ClaimsProcessingService { * * @param claimsRequired the required claims to check against * @param claimsSupplied the supplied claims to test - * @return the unmatched claims (if any), an empty set if the claims are satisfied, never null + * @return the result of the claims processing action */ - public Collection claimsAreSatisfied(Collection claimsRequired, Collection claimsSupplied); + public ClaimProcessingResult claimsAreSatisfied(Collection claimsRequired, Collection claimsSupplied); } diff --git a/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsProcessor.java b/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsOnAnyPolicy.java similarity index 87% rename from uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsProcessor.java rename to uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsOnAnyPolicy.java index 0ed4e0fadf..99f1403da8 100644 --- a/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsProcessor.java +++ b/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsOnAnyPolicy.java @@ -21,6 +21,7 @@ import java.util.HashSet; import org.mitre.uma.model.Claim; +import org.mitre.uma.model.ClaimProcessingResult; import org.mitre.uma.model.Policy; import org.mitre.uma.service.ClaimsProcessingService; import org.springframework.stereotype.Service; @@ -32,20 +33,20 @@ * @author jricher * */ -@Service("matchAllClaimsProcessor") -public class MatchAllClaimsProcessor implements ClaimsProcessingService { +@Service("matchAllClaimsOnAnyPolicy") +public class MatchAllClaimsOnAnyPolicy implements ClaimsProcessingService { /* (non-Javadoc) * @see org.mitre.uma.service.ClaimsProcessingService#claimsAreSatisfied(java.util.Collection, java.util.Collection) */ @Override - public Collection claimsAreSatisfied(Collection claimsRequired, Collection claimsSupplied) { + public ClaimProcessingResult claimsAreSatisfied(Collection claimsRequired, Collection claimsSupplied) { Collection allUnmatched = new HashSet<>(); for (Policy policy : claimsRequired) { Collection unmatched = checkIndividualClaims(policy.getClaimsRequired(), claimsSupplied); if (unmatched.isEmpty()) { // we found something that's satisfied the claims, let's go with it! - return unmatched; + return new ClaimProcessingResult(policy); } else { // otherwise add it to the stack to send back allUnmatched.addAll(unmatched); @@ -53,7 +54,7 @@ public Collection claimsAreSatisfied(Collection claimsRequired, C } // otherwise, tell the caller that we'll need some set of these fulfilled somehow - return allUnmatched; + return new ClaimProcessingResult(allUnmatched); } private Collection checkIndividualClaims(Collection claimsRequired, Collection claimsSupplied) { diff --git a/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java index 279ae64ac9..cdc10e1519 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java @@ -39,6 +39,7 @@ import org.mitre.openid.connect.view.JsonEntityView; import org.mitre.openid.connect.view.JsonErrorView; import org.mitre.uma.model.Claim; +import org.mitre.uma.model.ClaimProcessingResult; import org.mitre.uma.model.PermissionTicket; import org.mitre.uma.model.ResourceSet; import org.mitre.uma.service.ClaimsProcessingService; @@ -141,12 +142,12 @@ public String authorizationRequest(@RequestBody String jsonString, Model m, Auth } else { // claims weren't empty or missing, we need to check against what we have - Collection claimsUnmatched = claimsProcessingService.claimsAreSatisfied(rs.getPolicies(), ticket.getClaimsSupplied()); + ClaimProcessingResult result = claimsProcessingService.claimsAreSatisfied(rs.getPolicies(), ticket.getClaimsSupplied()); // we need to downscope this based on the required set that was matched if it was matched - if (claimsUnmatched.isEmpty()) { - // if the unmatched claims come back empty, by function contract that means we're happy and can issue a token + if (result.isSatisfied()) { + // the service found what it was looking for, issue a token OAuth2Authentication o2auth = (OAuth2Authentication) auth; @@ -175,7 +176,7 @@ public String authorizationRequest(@RequestBody String jsonString, Model m, Auth rpClaims.addProperty("redirect_user", true); rpClaims.addProperty("ticket", ticketValue); JsonArray req = new JsonArray(); - for (Claim claim : claimsUnmatched) { + for (Claim claim : result.getUnmatched()) { JsonObject c = new JsonObject(); c.addProperty("name", claim.getName()); c.addProperty("friendly_name", claim.getFriendlyName()); From b0935086c276ef99c65df94ca36ce6c855a299c1 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 29 Jun 2015 12:54:23 -0400 Subject: [PATCH 016/465] made claims processor take in policy set and ticket directly --- .../uma/service/ClaimsProcessingService.java | 12 ++++----- .../impl/MatchAllClaimsOnAnyPolicy.java | 24 ++++++++++++------ .../uma/web/AuthorizationRequestEndpoint.java | 25 ++----------------- 3 files changed, 23 insertions(+), 38 deletions(-) diff --git a/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java b/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java index a0688a43f0..1d05b8c7e0 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java @@ -17,11 +17,9 @@ package org.mitre.uma.service; -import java.util.Collection; - -import org.mitre.uma.model.Claim; import org.mitre.uma.model.ClaimProcessingResult; -import org.mitre.uma.model.Policy; +import org.mitre.uma.model.PermissionTicket; +import org.mitre.uma.model.ResourceSet; /** * @@ -38,10 +36,10 @@ public interface ClaimsProcessingService { * sufficient to fulfill the requirements given by the claims that * are required. * - * @param claimsRequired the required claims to check against - * @param claimsSupplied the supplied claims to test + * @param rs the required claims to check against + * @param ticket the supplied claims to test * @return the result of the claims processing action */ - public ClaimProcessingResult claimsAreSatisfied(Collection claimsRequired, Collection claimsSupplied); + public ClaimProcessingResult claimsAreSatisfied(ResourceSet rs, PermissionTicket ticket); } diff --git a/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsOnAnyPolicy.java b/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsOnAnyPolicy.java index 99f1403da8..f236bd7946 100644 --- a/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsOnAnyPolicy.java +++ b/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsOnAnyPolicy.java @@ -22,7 +22,9 @@ import org.mitre.uma.model.Claim; import org.mitre.uma.model.ClaimProcessingResult; +import org.mitre.uma.model.PermissionTicket; import org.mitre.uma.model.Policy; +import org.mitre.uma.model.ResourceSet; import org.mitre.uma.service.ClaimsProcessingService; import org.springframework.stereotype.Service; @@ -40,16 +42,22 @@ public class MatchAllClaimsOnAnyPolicy implements ClaimsProcessingService { * @see org.mitre.uma.service.ClaimsProcessingService#claimsAreSatisfied(java.util.Collection, java.util.Collection) */ @Override - public ClaimProcessingResult claimsAreSatisfied(Collection claimsRequired, Collection claimsSupplied) { + public ClaimProcessingResult claimsAreSatisfied(ResourceSet rs, PermissionTicket ticket) { Collection allUnmatched = new HashSet<>(); - for (Policy policy : claimsRequired) { - Collection unmatched = checkIndividualClaims(policy.getClaimsRequired(), claimsSupplied); - if (unmatched.isEmpty()) { - // we found something that's satisfied the claims, let's go with it! - return new ClaimProcessingResult(policy); + for (Policy policy : rs.getPolicies()) { + if (policy.getScopes().equals(ticket.getPermission().getScopes())) { + + Collection unmatched = checkIndividualClaims(policy.getClaimsRequired(), ticket.getClaimsSupplied()); + if (unmatched.isEmpty()) { + // we found something that's satisfied the claims, let's go with it! + return new ClaimProcessingResult(policy); + } else { + // otherwise add it to the stack to send back + allUnmatched.addAll(unmatched); + } } else { - // otherwise add it to the stack to send back - allUnmatched.addAll(unmatched); + // scopes didn't match, skip it + allUnmatched.addAll(policy.getClaimsRequired()); } } diff --git a/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java index cdc10e1519..128a257e9c 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java @@ -17,23 +17,12 @@ package org.mitre.uma.web; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; import java.util.Map; -import java.util.UUID; -import org.mitre.jwt.signer.service.JWTSigningAndValidationService; -import org.mitre.oauth2.model.AuthenticationHolderEntity; -import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.model.OAuth2AccessTokenEntity; -import org.mitre.oauth2.repository.AuthenticationHolderRepository; -import org.mitre.oauth2.repository.OAuth2TokenRepository; -import org.mitre.oauth2.service.ClientDetailsEntityService; import org.mitre.oauth2.service.OAuth2TokenEntityService; import org.mitre.oauth2.service.SystemScopeService; import org.mitre.oauth2.web.AuthenticationUtilities; -import org.mitre.openid.connect.config.ConfigurationPropertiesBean; import org.mitre.openid.connect.service.OIDCTokenService; import org.mitre.openid.connect.view.HttpCodeView; import org.mitre.openid.connect.view.JsonEntityView; @@ -49,31 +38,21 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.util.MimeTypeUtils; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.JsonPrimitive; -import com.nimbusds.jose.JWSAlgorithm; -import com.nimbusds.jose.JWSHeader; -import com.nimbusds.jwt.JWTClaimsSet; -import com.nimbusds.jwt.SignedJWT; /** * @author jricher @@ -142,13 +121,13 @@ public String authorizationRequest(@RequestBody String jsonString, Model m, Auth } else { // claims weren't empty or missing, we need to check against what we have - ClaimProcessingResult result = claimsProcessingService.claimsAreSatisfied(rs.getPolicies(), ticket.getClaimsSupplied()); + ClaimProcessingResult result = claimsProcessingService.claimsAreSatisfied(rs, ticket); - // we need to downscope this based on the required set that was matched if it was matched if (result.isSatisfied()) { // the service found what it was looking for, issue a token + // we need to downscope this based on the required set that was matched if it was matched OAuth2Authentication o2auth = (OAuth2Authentication) auth; OAuth2AccessTokenEntity token = umaTokenService.createRequestingPartyToken(o2auth, ticket); From af798705b428feafcdfeb708bde0af79f0faecce Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 29 Jun 2015 20:10:13 -0400 Subject: [PATCH 017/465] made claim values any JSON type, closes #853 --- .../convert/JsonElementStringConverter.java | 58 +++++++++++++++++++ .../main/java/org/mitre/uma/model/Claim.java | 12 +++- .../uma/web/ClaimsCollectionEndpoint.java | 17 +++--- .../web/ResourceSetRegistrationEndpoint.java | 8 +-- 4 files changed, 81 insertions(+), 14 deletions(-) create mode 100644 openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JsonElementStringConverter.java diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JsonElementStringConverter.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JsonElementStringConverter.java new file mode 100644 index 0000000000..a2918bddce --- /dev/null +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JsonElementStringConverter.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright 2015 The MITRE Corporation + * and the MIT Kerberos and Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +package org.mitre.oauth2.model.convert; + +import javax.persistence.AttributeConverter; +import javax.persistence.Converter; + +import com.google.common.base.Strings; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +/** + * @author jricher + * + */ +@Converter +public class JsonElementStringConverter implements AttributeConverter { + + private JsonParser parser = new JsonParser(); + + @Override + public String convertToDatabaseColumn(JsonElement attribute) { + if (attribute != null) { + return attribute.toString(); + } else { + return null; + } + } + + /* (non-Javadoc) + * @see javax.persistence.AttributeConverter#convertToEntityAttribute(java.lang.Object) + */ + @Override + public JsonElement convertToEntityAttribute(String dbData) { + if (!Strings.isNullOrEmpty(dbData)) { + return parser.parse(dbData); + } else { + return null; + } + } + +} diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/Claim.java b/openid-connect-common/src/main/java/org/mitre/uma/model/Claim.java index 2a2beac984..fd88af6a0e 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/Claim.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/Claim.java @@ -22,6 +22,7 @@ import javax.persistence.Basic; import javax.persistence.CollectionTable; import javax.persistence.Column; +import javax.persistence.Convert; import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.FetchType; @@ -31,6 +32,10 @@ import javax.persistence.JoinColumn; import javax.persistence.Table; +import org.mitre.oauth2.model.convert.JsonElementStringConverter; + +import com.google.gson.JsonElement; + /** * @author jricher * @@ -43,7 +48,7 @@ public class Claim { private String name; private String friendlyName; private String claimType; - private String value; + private JsonElement value; private Set claimTokenFormat; private Set issuer; @@ -150,13 +155,14 @@ public void setIssuer(Set issuer) { */ @Basic @Column(name = "claim_value") - public String getValue() { + @Convert(converter = JsonElementStringConverter.class) + public JsonElement getValue() { return value; } /** * @param value the value to set */ - public void setValue(String value) { + public void setValue(JsonElement value) { this.value = value; } } diff --git a/uma-server/src/main/java/org/mitre/uma/web/ClaimsCollectionEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/ClaimsCollectionEndpoint.java index 5eab049b1d..324a098042 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/ClaimsCollectionEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/ClaimsCollectionEndpoint.java @@ -24,7 +24,6 @@ import org.mitre.openid.connect.model.OIDCAuthenticationToken; import org.mitre.openid.connect.model.UserInfo; import org.mitre.openid.connect.view.HttpCodeView; -import org.mitre.openid.connect.view.JsonErrorView; import org.mitre.uma.model.Claim; import org.mitre.uma.model.PermissionTicket; import org.mitre.uma.service.PermissionService; @@ -42,6 +41,8 @@ import com.google.common.base.Strings; import com.google.common.collect.Sets; +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; /** * @@ -90,11 +91,13 @@ public String collectClaims(@RequestParam("client_id") String clientId, @Request String issuer = auth.getIssuer(); UserInfo userInfo = auth.getUserInfo(); - claimsSupplied.add(mkClaim(issuer, "sub", auth.getSub())); - claimsSupplied.add(mkClaim(issuer, "email", userInfo.getEmail())); - claimsSupplied.add(mkClaim(issuer, "phone_number", auth.getUserInfo().getPhoneNumber())); - claimsSupplied.add(mkClaim(issuer, "preferred_username", auth.getUserInfo().getPreferredUsername())); - claimsSupplied.add(mkClaim(issuer, "profile", auth.getUserInfo().getProfile())); + claimsSupplied.add(mkClaim(issuer, "sub", new JsonPrimitive(auth.getSub()))); + claimsSupplied.add(mkClaim(issuer, "email", new JsonPrimitive(userInfo.getEmail()))); + claimsSupplied.add(mkClaim(issuer, "email_verified", new JsonPrimitive(userInfo.getEmailVerified()))); + claimsSupplied.add(mkClaim(issuer, "phone_number", new JsonPrimitive(auth.getUserInfo().getPhoneNumber()))); + claimsSupplied.add(mkClaim(issuer, "phone_number_verified", new JsonPrimitive(auth.getUserInfo().getPhoneNumberVerified()))); + claimsSupplied.add(mkClaim(issuer, "preferred_username", new JsonPrimitive(auth.getUserInfo().getPreferredUsername()))); + claimsSupplied.add(mkClaim(issuer, "profile", new JsonPrimitive(auth.getUserInfo().getProfile()))); ticket.setClaimsSupplied(claimsSupplied); @@ -120,7 +123,7 @@ public String collectClaims(@RequestParam("client_id") String clientId, @Request } - private Claim mkClaim(String issuer, String name, String value) { + private Claim mkClaim(String issuer, String name, JsonElement value) { Claim c = new Claim(); c.setIssuer(Sets.newHashSet(issuer)); c.setName(name); diff --git a/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java index 50a04028a4..aae0c413c5 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java @@ -55,6 +55,7 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import com.google.gson.JsonParser; +import com.google.gson.JsonPrimitive; import static org.mitre.oauth2.web.AuthenticationUtilities.ensureOAuthScope; import static org.mitre.util.JsonUtils.getAsLong; @@ -129,16 +130,15 @@ public String createResourceSet(@RequestBody String jsonString, Model m, Authent Claim e = new Claim(); e.setIssuer(Sets.newHashSet("https://healthauth.org/")); e.setName("email"); - e.setValue("alice@healthauth.org"); + e.setValue(new JsonPrimitive("alice@healthauth.org")); claims.add(e); - /* TODO: claims need to be multi-typed Claim ev = new Claim(); ev.setIssuer(Sets.newHashSet("https://healthauth.org/")); e.setName("email_verified"); - ev.setValue(true); + ev.setValue(new JsonPrimitive(true)); claims.add(e); - */ + Policy reqired = new Policy(); reqired.setScopes(rs.getScopes()); reqired.setClaimsRequired(claims); From 7909e3e9cea3aaaf6fb4cc333ca4e2ab3e122f8a Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 29 Jun 2015 20:55:36 -0400 Subject: [PATCH 018/465] made claim collection null safe --- .../uma/web/ClaimsCollectionEndpoint.java | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/uma-server/src/main/java/org/mitre/uma/web/ClaimsCollectionEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/ClaimsCollectionEndpoint.java index 324a098042..b34d6e9eb0 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/ClaimsCollectionEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/ClaimsCollectionEndpoint.java @@ -92,12 +92,24 @@ public String collectClaims(@RequestParam("client_id") String clientId, @Request UserInfo userInfo = auth.getUserInfo(); claimsSupplied.add(mkClaim(issuer, "sub", new JsonPrimitive(auth.getSub()))); - claimsSupplied.add(mkClaim(issuer, "email", new JsonPrimitive(userInfo.getEmail()))); - claimsSupplied.add(mkClaim(issuer, "email_verified", new JsonPrimitive(userInfo.getEmailVerified()))); - claimsSupplied.add(mkClaim(issuer, "phone_number", new JsonPrimitive(auth.getUserInfo().getPhoneNumber()))); - claimsSupplied.add(mkClaim(issuer, "phone_number_verified", new JsonPrimitive(auth.getUserInfo().getPhoneNumberVerified()))); - claimsSupplied.add(mkClaim(issuer, "preferred_username", new JsonPrimitive(auth.getUserInfo().getPreferredUsername()))); - claimsSupplied.add(mkClaim(issuer, "profile", new JsonPrimitive(auth.getUserInfo().getProfile()))); + if (userInfo.getEmail() != null) { + claimsSupplied.add(mkClaim(issuer, "email", new JsonPrimitive(userInfo.getEmail()))); + } + if (userInfo.getEmailVerified() != null) { + claimsSupplied.add(mkClaim(issuer, "email_verified", new JsonPrimitive(userInfo.getEmailVerified()))); + } + if (userInfo.getPhoneNumber() != null) { + claimsSupplied.add(mkClaim(issuer, "phone_number", new JsonPrimitive(auth.getUserInfo().getPhoneNumber()))); + } + if (userInfo.getPhoneNumberVerified() != null) { + claimsSupplied.add(mkClaim(issuer, "phone_number_verified", new JsonPrimitive(auth.getUserInfo().getPhoneNumberVerified()))); + } + if (userInfo.getPreferredUsername() != null) { + claimsSupplied.add(mkClaim(issuer, "preferred_username", new JsonPrimitive(auth.getUserInfo().getPreferredUsername()))); + } + if (userInfo.getProfile() != null) { + claimsSupplied.add(mkClaim(issuer, "profile", new JsonPrimitive(auth.getUserInfo().getProfile()))); + } ticket.setClaimsSupplied(claimsSupplied); From a8a6e7bf311b1ab23aae1cb643a1a9a9a0e1544d Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 29 Jun 2015 20:56:05 -0400 Subject: [PATCH 019/465] downscope resulting token based on policy --- .../org/mitre/uma/service/UmaTokenService.java | 6 ++---- .../service/impl/DefaultUmaTokenService.java | 14 ++++++++++++-- .../impl/MatchAllClaimsOnAnyPolicy.java | 18 ++++++------------ .../uma/web/AuthorizationRequestEndpoint.java | 2 +- 4 files changed, 21 insertions(+), 19 deletions(-) diff --git a/openid-connect-common/src/main/java/org/mitre/uma/service/UmaTokenService.java b/openid-connect-common/src/main/java/org/mitre/uma/service/UmaTokenService.java index c644abbdb3..88c6f92b65 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/service/UmaTokenService.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/service/UmaTokenService.java @@ -19,6 +19,7 @@ import org.mitre.oauth2.model.OAuth2AccessTokenEntity; import org.mitre.uma.model.PermissionTicket; +import org.mitre.uma.model.Policy; import org.springframework.security.oauth2.provider.OAuth2Authentication; /** @@ -32,10 +33,7 @@ public interface UmaTokenService { /** * Create the RPT from the given authentication and ticket. * - * @param o2auth - * @param ticket - * @return */ - public OAuth2AccessTokenEntity createRequestingPartyToken(OAuth2Authentication o2auth, PermissionTicket ticket); + public OAuth2AccessTokenEntity createRequestingPartyToken(OAuth2Authentication o2auth, PermissionTicket ticket, Policy policy); } diff --git a/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultUmaTokenService.java b/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultUmaTokenService.java index 8d77911aee..4d32e79056 100644 --- a/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultUmaTokenService.java +++ b/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultUmaTokenService.java @@ -18,6 +18,8 @@ package org.mitre.uma.service.impl; import java.util.Date; +import java.util.HashSet; +import java.util.Set; import java.util.UUID; import org.mitre.jwt.signer.service.JWTSigningAndValidationService; @@ -28,7 +30,9 @@ import org.mitre.oauth2.service.ClientDetailsEntityService; import org.mitre.oauth2.service.OAuth2TokenEntityService; import org.mitre.openid.connect.config.ConfigurationPropertiesBean; +import org.mitre.uma.model.Permission; import org.mitre.uma.model.PermissionTicket; +import org.mitre.uma.model.Policy; import org.mitre.uma.service.UmaTokenService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.oauth2.provider.OAuth2Authentication; @@ -65,7 +69,7 @@ public class DefaultUmaTokenService implements UmaTokenService { @Override - public OAuth2AccessTokenEntity createRequestingPartyToken(OAuth2Authentication o2auth, PermissionTicket ticket) { + public OAuth2AccessTokenEntity createRequestingPartyToken(OAuth2Authentication o2auth, PermissionTicket ticket, Policy policy) { OAuth2AccessTokenEntity token = new OAuth2AccessTokenEntity(); AuthenticationHolderEntity authHolder = new AuthenticationHolderEntity(); authHolder.setAuthentication(o2auth); @@ -76,8 +80,14 @@ public OAuth2AccessTokenEntity createRequestingPartyToken(OAuth2Authentication o ClientDetailsEntity client = clientService.loadClientByClientId(o2auth.getOAuth2Request().getClientId()); token.setClient(client); - token.setPermissions(Sets.newHashSet(ticket.getPermission())); + Set ticketScopes = ticket.getPermission().getScopes(); + Set policyScopes = policy.getScopes(); + Permission perm = new Permission(); + perm.setResourceSet(ticket.getPermission().getResourceSet()); + perm.setScopes(new HashSet<>(Sets.intersection(ticketScopes, policyScopes))); + + token.setPermissions(Sets.newHashSet(perm)); JWTClaimsSet claims = new JWTClaimsSet(); diff --git a/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsOnAnyPolicy.java b/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsOnAnyPolicy.java index f236bd7946..87ee2f6939 100644 --- a/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsOnAnyPolicy.java +++ b/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsOnAnyPolicy.java @@ -45,19 +45,13 @@ public class MatchAllClaimsOnAnyPolicy implements ClaimsProcessingService { public ClaimProcessingResult claimsAreSatisfied(ResourceSet rs, PermissionTicket ticket) { Collection allUnmatched = new HashSet<>(); for (Policy policy : rs.getPolicies()) { - if (policy.getScopes().equals(ticket.getPermission().getScopes())) { - - Collection unmatched = checkIndividualClaims(policy.getClaimsRequired(), ticket.getClaimsSupplied()); - if (unmatched.isEmpty()) { - // we found something that's satisfied the claims, let's go with it! - return new ClaimProcessingResult(policy); - } else { - // otherwise add it to the stack to send back - allUnmatched.addAll(unmatched); - } + Collection unmatched = checkIndividualClaims(policy.getClaimsRequired(), ticket.getClaimsSupplied()); + if (unmatched.isEmpty()) { + // we found something that's satisfied the claims, let's go with it! + return new ClaimProcessingResult(policy); } else { - // scopes didn't match, skip it - allUnmatched.addAll(policy.getClaimsRequired()); + // otherwise add it to the stack to send back + allUnmatched.addAll(unmatched); } } diff --git a/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java index 128a257e9c..28ad2d2f31 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java @@ -130,7 +130,7 @@ public String authorizationRequest(@RequestBody String jsonString, Model m, Auth // we need to downscope this based on the required set that was matched if it was matched OAuth2Authentication o2auth = (OAuth2Authentication) auth; - OAuth2AccessTokenEntity token = umaTokenService.createRequestingPartyToken(o2auth, ticket); + OAuth2AccessTokenEntity token = umaTokenService.createRequestingPartyToken(o2auth, ticket, result.getMatched()); // if we have an inbound RPT, throw it out because we're replacing it if (incomingRpt != null) { From bfd70efcc30ae2c799ba0cdaf5915fb3adaaf918 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 29 Jun 2015 21:00:41 -0400 Subject: [PATCH 020/465] tweak demo claim values for testing --- .../org/mitre/uma/web/ResourceSetRegistrationEndpoint.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java index aae0c413c5..99964de30d 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java @@ -135,12 +135,12 @@ public String createResourceSet(@RequestBody String jsonString, Model m, Authent Claim ev = new Claim(); ev.setIssuer(Sets.newHashSet("https://healthauth.org/")); - e.setName("email_verified"); + ev.setName("email_verified"); ev.setValue(new JsonPrimitive(true)); - claims.add(e); + claims.add(ev); Policy reqired = new Policy(); - reqired.setScopes(rs.getScopes()); + reqired.setScopes(Sets.newHashSet("foo", "batman")); reqired.setClaimsRequired(claims); rs.setPolicies(Sets.newHashSet(reqired)); From 6703db234d7eba80ba9f1a013286bcc9918a1109 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 1 Jul 2015 18:23:33 -0400 Subject: [PATCH 021/465] added equals/hashCode/toString on UMA model objects --- .../main/java/org/mitre/uma/model/Claim.java | 89 +++++++++++++++ .../main/java/org/mitre/uma/model/Policy.java | 68 +++++++++++ .../java/org/mitre/uma/model/ResourceSet.java | 108 ++++++++++++++++++ 3 files changed, 265 insertions(+) diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/Claim.java b/openid-connect-common/src/main/java/org/mitre/uma/model/Claim.java index fd88af6a0e..856617a123 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/Claim.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/Claim.java @@ -165,4 +165,93 @@ public JsonElement getValue() { public void setValue(JsonElement value) { this.value = value; } + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "Claim [id=" + id + ", name=" + name + ", friendlyName=" + friendlyName + ", claimType=" + claimType + ", value=" + value + ", claimTokenFormat=" + claimTokenFormat + ", issuer=" + issuer + "]"; + } + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((claimTokenFormat == null) ? 0 : claimTokenFormat.hashCode()); + result = prime * result + ((claimType == null) ? 0 : claimType.hashCode()); + result = prime * result + ((friendlyName == null) ? 0 : friendlyName.hashCode()); + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((issuer == null) ? 0 : issuer.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((value == null) ? 0 : value.hashCode()); + return result; + } + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Claim other = (Claim) obj; + if (claimTokenFormat == null) { + if (other.claimTokenFormat != null) { + return false; + } + } else if (!claimTokenFormat.equals(other.claimTokenFormat)) { + return false; + } + if (claimType == null) { + if (other.claimType != null) { + return false; + } + } else if (!claimType.equals(other.claimType)) { + return false; + } + if (friendlyName == null) { + if (other.friendlyName != null) { + return false; + } + } else if (!friendlyName.equals(other.friendlyName)) { + return false; + } + if (id == null) { + if (other.id != null) { + return false; + } + } else if (!id.equals(other.id)) { + return false; + } + if (issuer == null) { + if (other.issuer != null) { + return false; + } + } else if (!issuer.equals(other.issuer)) { + return false; + } + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + if (value == null) { + if (other.value != null) { + return false; + } + } else if (!value.equals(other.value)) { + return false; + } + return true; + } } diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/Policy.java b/openid-connect-common/src/main/java/org/mitre/uma/model/Policy.java index 286fb578a4..b96da6bf72 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/Policy.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/Policy.java @@ -122,5 +122,73 @@ public Set getScopes() { public void setScopes(Set scopes) { this.scopes = scopes; } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "Policy [id=" + id + ", name=" + name + ", claimsRequired=" + claimsRequired + ", scopes=" + scopes + "]"; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((claimsRequired == null) ? 0 : claimsRequired.hashCode()); + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((scopes == null) ? 0 : scopes.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Policy other = (Policy) obj; + if (claimsRequired == null) { + if (other.claimsRequired != null) { + return false; + } + } else if (!claimsRequired.equals(other.claimsRequired)) { + return false; + } + if (id == null) { + if (other.id != null) { + return false; + } + } else if (!id.equals(other.id)) { + return false; + } + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + if (scopes == null) { + if (other.scopes != null) { + return false; + } + } else if (!scopes.equals(other.scopes)) { + return false; + } + return true; + } } diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/ResourceSet.java b/openid-connect-common/src/main/java/org/mitre/uma/model/ResourceSet.java index bb4c680367..de951aebd4 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/ResourceSet.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/ResourceSet.java @@ -209,6 +209,114 @@ public Collection getPolicies() { public void setPolicies(Collection policies) { this.policies = policies; } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "ResourceSet [id=" + id + ", name=" + name + ", uri=" + uri + ", type=" + type + ", scopes=" + scopes + ", iconUri=" + iconUri + ", owner=" + owner + ", clientId=" + clientId + ", policies=" + policies + "]"; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((clientId == null) ? 0 : clientId.hashCode()); + result = prime * result + ((iconUri == null) ? 0 : iconUri.hashCode()); + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((owner == null) ? 0 : owner.hashCode()); + result = prime * result + ((policies == null) ? 0 : policies.hashCode()); + result = prime * result + ((scopes == null) ? 0 : scopes.hashCode()); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + result = prime * result + ((uri == null) ? 0 : uri.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + ResourceSet other = (ResourceSet) obj; + if (clientId == null) { + if (other.clientId != null) { + return false; + } + } else if (!clientId.equals(other.clientId)) { + return false; + } + if (iconUri == null) { + if (other.iconUri != null) { + return false; + } + } else if (!iconUri.equals(other.iconUri)) { + return false; + } + if (id == null) { + if (other.id != null) { + return false; + } + } else if (!id.equals(other.id)) { + return false; + } + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + if (owner == null) { + if (other.owner != null) { + return false; + } + } else if (!owner.equals(other.owner)) { + return false; + } + if (policies == null) { + if (other.policies != null) { + return false; + } + } else if (!policies.equals(other.policies)) { + return false; + } + if (scopes == null) { + if (other.scopes != null) { + return false; + } + } else if (!scopes.equals(other.scopes)) { + return false; + } + if (type == null) { + if (other.type != null) { + return false; + } + } else if (!type.equals(other.type)) { + return false; + } + if (uri == null) { + if (other.uri != null) { + return false; + } + } else if (!uri.equals(other.uri)) { + return false; + } + return true; + } From d7af4b2cf9b8048b293d2c325bd3d6c74cd90110 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 1 Jul 2015 18:23:55 -0400 Subject: [PATCH 022/465] added scope consistent check to resource set service --- .../impl/DefaultResourceSetService.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultResourceSetService.java b/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultResourceSetService.java index 14716e2241..0cbd2a0742 100644 --- a/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultResourceSetService.java +++ b/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultResourceSetService.java @@ -19,6 +19,7 @@ import java.util.Collection; +import org.mitre.uma.model.Policy; import org.mitre.uma.model.ResourceSet; import org.mitre.uma.repository.ResourceSetRepository; import org.mitre.uma.service.ResourceSetService; @@ -48,6 +49,10 @@ public ResourceSet saveNew(ResourceSet rs) { throw new IllegalArgumentException("Can't save a new resource set with an ID already set to it."); } + if (!checkScopeConsistency(rs)) { + throw new IllegalArgumentException("Can't save a resource set with inconsistent claims."); + } + ResourceSet saved = repository.save(rs); return saved; @@ -68,6 +73,10 @@ public ResourceSet update(ResourceSet oldRs, ResourceSet newRs) { throw new IllegalArgumentException("Resource set IDs mismatched"); } + + if (!checkScopeConsistency(newRs)) { + throw new IllegalArgumentException("Can't save a resource set with inconsistent claims."); + } newRs.setOwner(oldRs.getOwner()); // preserve the owner tag across updates newRs.setClientId(oldRs.getClientId()); // preserve the client id across updates @@ -93,6 +102,14 @@ public Collection getAllForOwnerAndClient(String owner, String clie return repository.getAllForOwnerAndClient(owner, clientId); } - + private boolean checkScopeConsistency(ResourceSet rs) { + for (Policy policy : rs.getPolicies()) { + if (!rs.getScopes().containsAll(policy.getScopes())) { + return false; + } + } + // we've checked everything, we're good + return true; + } } From f0d628bf273f174e76365a45ec20bd91e20d0a69 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 1 Jul 2015 18:24:13 -0400 Subject: [PATCH 023/465] made Policy API fit the new data model (used to be Claims API) --- .../java/org/mitre/uma/web/ClaimsAPI.java | 162 --------- .../java/org/mitre/uma/web/PolicyAPI.java | 330 ++++++++++++++++++ 2 files changed, 330 insertions(+), 162 deletions(-) delete mode 100644 uma-server/src/main/java/org/mitre/uma/web/ClaimsAPI.java create mode 100644 uma-server/src/main/java/org/mitre/uma/web/PolicyAPI.java diff --git a/uma-server/src/main/java/org/mitre/uma/web/ClaimsAPI.java b/uma-server/src/main/java/org/mitre/uma/web/ClaimsAPI.java deleted file mode 100644 index f7341b23d1..0000000000 --- a/uma-server/src/main/java/org/mitre/uma/web/ClaimsAPI.java +++ /dev/null @@ -1,162 +0,0 @@ -/******************************************************************************* - * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *******************************************************************************/ - -package org.mitre.uma.web; - -import java.util.Collection; -import java.util.Set; - -import org.mitre.oauth2.service.SystemScopeService; -import org.mitre.openid.connect.view.HttpCodeView; -import org.mitre.openid.connect.view.JsonEntityView; -import org.mitre.openid.connect.view.JsonErrorView; -import org.mitre.openid.connect.web.RootController; -import org.mitre.uma.model.Claim; -import org.mitre.uma.model.Policy; -import org.mitre.uma.model.ResourceSet; -import org.mitre.uma.service.ResourceSetService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.util.MimeTypeUtils; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; - -import com.google.common.reflect.TypeToken; -import com.google.gson.Gson; - -import static org.mitre.oauth2.web.AuthenticationUtilities.ensureOAuthScope; - -/** - * @author jricher - * - */ -@Controller -@RequestMapping("/" + ClaimsAPI.URL) -@PreAuthorize("hasRole('ROLE_USER')") -public class ClaimsAPI { - - // - // - // FIXME - // - // - - // Logger for this class - private static final Logger logger = LoggerFactory.getLogger(ClaimsAPI.class); - - public static final String URL = RootController.API_URL + "/claims"; - - @Autowired - private ResourceSetService resourceSetService; - - @RequestMapping(value = "", method = RequestMethod.GET, produces = MimeTypeUtils.APPLICATION_JSON_VALUE) - public String getResourceSetsForCurrentUser(Model m, Authentication auth) { - - Collection resourceSets = resourceSetService.getAllForOwner(auth.getName()); - - m.addAttribute(JsonEntityView.ENTITY, resourceSets); - - return JsonEntityView.VIEWNAME; - } - - @RequestMapping(value = "/{rsid}", method = RequestMethod.GET, produces = MimeTypeUtils.APPLICATION_JSON_VALUE) - public String getClaimsForResourceSet(@PathVariable (value = "rsid") Long rsid, Model m, Authentication auth) { - - ResourceSet rs = resourceSetService.getById(rsid); - - if (rs == null) { - m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND); - return HttpCodeView.VIEWNAME; - } - - if (!rs.getOwner().equals(auth.getName())) { - // authenticated user didn't match the owner of the resource set - m.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN); - return HttpCodeView.VIEWNAME; - } - - m.addAttribute(JsonEntityView.ENTITY, rs.getPolicies()); - - return JsonEntityView.VIEWNAME; - } - - @RequestMapping(value = "/{rsid}", method = RequestMethod.PUT, consumes = MimeTypeUtils.APPLICATION_JSON_VALUE, produces = MimeTypeUtils.APPLICATION_JSON_VALUE) - public String setClaimsForResourceSet(@PathVariable (value = "rsid") Long rsid, @RequestBody String jsonString, Model m, Authentication auth) { - - ResourceSet rs = resourceSetService.getById(rsid); - - if (rs == null) { - m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND); - return HttpCodeView.VIEWNAME; - } - - if (!rs.getOwner().equals(auth.getName())) { - // authenticated user didn't match the owner of the resource set - m.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN); - return HttpCodeView.VIEWNAME; - } - - @SuppressWarnings("serial") - Set claims = (new Gson()).fromJson(jsonString, new TypeToken>() {}.getType()); - - //rs.setClaimsRequired(claims); - - resourceSetService.update(rs, rs); - - m.addAttribute(JsonEntityView.ENTITY, rs.getPolicies()); - - return JsonEntityView.VIEWNAME; - } - - @RequestMapping(value = "/{rsid}", method = RequestMethod.DELETE, produces = MimeTypeUtils.APPLICATION_JSON_VALUE) - public String deleteResourceSet(@PathVariable ("rsid") Long id, Model m, Authentication auth) { - - ResourceSet rs = resourceSetService.getById(id); - - if (rs == null) { - m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND); - m.addAttribute(JsonErrorView.ERROR, "not_found"); - return JsonErrorView.VIEWNAME; - } else { - if (!auth.getName().equals(rs.getOwner())) { - - logger.warn("Unauthorized resource set request from bad user; expected " + rs.getOwner() + " got " + auth.getName()); - - // it wasn't issued to this user - m.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN); - return JsonErrorView.VIEWNAME; - } else { - - resourceSetService.remove(rs); - - m.addAttribute(HttpCodeView.CODE, HttpStatus.NO_CONTENT); - return HttpCodeView.VIEWNAME; - } - - } - } - -} diff --git a/uma-server/src/main/java/org/mitre/uma/web/PolicyAPI.java b/uma-server/src/main/java/org/mitre/uma/web/PolicyAPI.java new file mode 100644 index 0000000000..03862397e9 --- /dev/null +++ b/uma-server/src/main/java/org/mitre/uma/web/PolicyAPI.java @@ -0,0 +1,330 @@ +/******************************************************************************* + * Copyright 2015 The MITRE Corporation + * and the MIT Kerberos and Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +package org.mitre.uma.web; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import org.mitre.openid.connect.view.HttpCodeView; +import org.mitre.openid.connect.view.JsonEntityView; +import org.mitre.openid.connect.view.JsonErrorView; +import org.mitre.openid.connect.web.RootController; +import org.mitre.uma.model.Claim; +import org.mitre.uma.model.Policy; +import org.mitre.uma.model.ResourceSet; +import org.mitre.uma.service.ResourceSetService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.util.MimeTypeUtils; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import com.google.common.collect.Sets; +import com.google.gson.Gson; + +/** + * API for managing policies on resource sets. + * + * @author jricher + * + */ +@Controller +@RequestMapping("/" + PolicyAPI.URL) +@PreAuthorize("hasRole('ROLE_USER')") +public class PolicyAPI { + + // Logger for this class + private static final Logger logger = LoggerFactory.getLogger(PolicyAPI.class); + + public static final String URL = RootController.API_URL + "/policy"; + + private Gson gson = new Gson(); + + @Autowired + private ResourceSetService resourceSetService; + + /** + * List all resource sets for the current user + * @param m + * @param auth + * @return + */ + @RequestMapping(value = "", method = RequestMethod.GET, produces = MimeTypeUtils.APPLICATION_JSON_VALUE) + public String getResourceSetsForCurrentUser(Model m, Authentication auth) { + + Collection resourceSets = resourceSetService.getAllForOwner(auth.getName()); + + m.addAttribute(JsonEntityView.ENTITY, resourceSets); + + return JsonEntityView.VIEWNAME; + } + + /** + * List all the policies for the given resource set + * @param rsid + * @param m + * @param auth + * @return + */ + @RequestMapping(value = "/{rsid}", method = RequestMethod.GET, produces = MimeTypeUtils.APPLICATION_JSON_VALUE) + public String getPoliciesForResourceSet(@PathVariable (value = "rsid") Long rsid, Model m, Authentication auth) { + + ResourceSet rs = resourceSetService.getById(rsid); + + if (rs == null) { + m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND); + return HttpCodeView.VIEWNAME; + } + + if (!rs.getOwner().equals(auth.getName())) { + logger.warn("Unauthorized resource set request from bad user; expected " + rs.getOwner() + " got " + auth.getName()); + + // authenticated user didn't match the owner of the resource set + m.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN); + return HttpCodeView.VIEWNAME; + } + + m.addAttribute(JsonEntityView.ENTITY, rs.getPolicies()); + + return JsonEntityView.VIEWNAME; + } + + /** + * Create a new policy on the given resource set + * @param rsid + * @param m + * @param auth + * @return + */ + @RequestMapping(value = "/{rsid}", method = RequestMethod.POST, produces = MimeTypeUtils.APPLICATION_JSON_VALUE) + public String createNewPolicyForResourceSet(@PathVariable (value = "rsid") Long rsid, @RequestBody String jsonString, Model m, Authentication auth) { + ResourceSet rs = resourceSetService.getById(rsid); + + if (rs == null) { + m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND); + return HttpCodeView.VIEWNAME; + } + + if (!rs.getOwner().equals(auth.getName())) { + logger.warn("Unauthorized resource set request from bad user; expected " + rs.getOwner() + " got " + auth.getName()); + + // authenticated user didn't match the owner of the resource set + m.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN); + return HttpCodeView.VIEWNAME; + } + + Policy p = gson.fromJson(jsonString, Policy.class); + + if (p.getId() != null) { + logger.warn("Tried to add a policy with a non-null ID: " + p.getId()); + m.addAttribute(HttpCodeView.CODE, HttpStatus.BAD_REQUEST); + return HttpCodeView.VIEWNAME; + } + + for (Claim claim : p.getClaimsRequired()) { + if (claim.getId() != null) { + logger.warn("Tried to add a policy with a non-null claim ID: " + claim.getId()); + m.addAttribute(HttpCodeView.CODE, HttpStatus.BAD_REQUEST); + return HttpCodeView.VIEWNAME; + } + } + + rs.getPolicies().add(p); + ResourceSet saved = resourceSetService.update(rs, rs); + + // find the new policy object + Collection newPolicies = Sets.difference(new HashSet<>(saved.getPolicies()), new HashSet<>(rs.getPolicies())); + + if (newPolicies.size() == 1) { + Policy newPolicy = newPolicies.iterator().next(); + m.addAttribute(JsonEntityView.ENTITY, newPolicy); + return JsonEntityView.VIEWNAME; + } else { + logger.warn("Unexpected result trying to add a new policy object: " + newPolicies); + m.addAttribute(HttpCodeView.CODE, HttpStatus.INTERNAL_SERVER_ERROR); + return HttpCodeView.VIEWNAME; + } + + } + + /** + * Get a specific policy + * @param rsid + * @param pid + * @param m + * @param auth + * @return + */ + @RequestMapping(value = "/{rsid}/{pid}", method = RequestMethod.GET, produces = MimeTypeUtils.APPLICATION_JSON_VALUE) + public String getPolicy(@PathVariable (value = "rsid") Long rsid, @PathVariable (value = "pid") Long pid, Model m, Authentication auth) { + + ResourceSet rs = resourceSetService.getById(rsid); + + if (rs == null) { + m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND); + return HttpCodeView.VIEWNAME; + } + + if (!rs.getOwner().equals(auth.getName())) { + logger.warn("Unauthorized resource set request from bad user; expected " + rs.getOwner() + " got " + auth.getName()); + + // authenticated user didn't match the owner of the resource set + m.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN); + return HttpCodeView.VIEWNAME; + } + + for (Policy policy : rs.getPolicies()) { + if (policy.getId().equals(pid)) { + // found it! + m.addAttribute(JsonEntityView.ENTITY, policy); + return JsonEntityView.VIEWNAME; + } + } + + // if we made it this far, we haven't found it + m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND); + return HttpCodeView.VIEWNAME; + } + + /** + * Update a specific policy + * @param rsid + * @param pid + * @param jsonString + * @param m + * @param auth + * @return + */ + @RequestMapping(value = "/{rsid}/{pid}", method = RequestMethod.PUT, consumes = MimeTypeUtils.APPLICATION_JSON_VALUE, produces = MimeTypeUtils.APPLICATION_JSON_VALUE) + public String setClaimsForResourceSet(@PathVariable (value = "rsid") Long rsid, @PathVariable (value = "pid") Long pid, @RequestBody String jsonString, Model m, Authentication auth) { + + ResourceSet rs = resourceSetService.getById(rsid); + + if (rs == null) { + m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND); + return HttpCodeView.VIEWNAME; + } + + if (!rs.getOwner().equals(auth.getName())) { + logger.warn("Unauthorized resource set request from bad user; expected " + rs.getOwner() + " got " + auth.getName()); + + // authenticated user didn't match the owner of the resource set + m.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN); + return HttpCodeView.VIEWNAME; + } + + Policy p = gson.fromJson(jsonString, Policy.class); + + if (!pid.equals(p.getId())) { + logger.warn("Policy ID mismatch, expected " + pid + " got " + p.getId()); + + m.addAttribute(HttpCodeView.CODE, HttpStatus.BAD_REQUEST); + return HttpCodeView.VIEWNAME; + } + + for (Policy policy : rs.getPolicies()) { + if (policy.getId().equals(pid)) { + // found it! + + // find the existing claim IDs, make sure we're not overwriting anything from another policy + Set claimIds = new HashSet<>(); + for (Claim claim : policy.getClaimsRequired()) { + claimIds.add(claim.getId()); + } + + for (Claim claim : p.getClaimsRequired()) { + if (claim.getId() != null && !claimIds.contains(claim.getId())) { + logger.warn("Tried to add a policy with a an unmatched claim ID: got " + claim.getId() + " expected " + claimIds); + m.addAttribute(HttpCodeView.CODE, HttpStatus.BAD_REQUEST); + return HttpCodeView.VIEWNAME; + } + } + + // update the existing object with the new values + policy.setClaimsRequired(p.getClaimsRequired()); + policy.setName(p.getName()); + policy.setScopes(p.getScopes()); + + resourceSetService.update(rs, rs); + + m.addAttribute(JsonEntityView.ENTITY, policy); + return JsonEntityView.VIEWNAME; + } + } + + // if we made it this far, we haven't found it + m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND); + return HttpCodeView.VIEWNAME; + } + + /** + * Delete a specific policy + * @param rsid + * @param pid + * @param m + * @param auth + * @return + */ + @RequestMapping(value = "/{rsid}/{pid}", method = RequestMethod.DELETE, produces = MimeTypeUtils.APPLICATION_JSON_VALUE) + public String deleteResourceSet(@PathVariable ("rsid") Long rsid, @PathVariable (value = "pid") Long pid, Model m, Authentication auth) { + + ResourceSet rs = resourceSetService.getById(rsid); + + if (rs == null) { + m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND); + m.addAttribute(JsonErrorView.ERROR, "not_found"); + return JsonErrorView.VIEWNAME; + } + + if (!auth.getName().equals(rs.getOwner())) { + + logger.warn("Unauthorized resource set request from bad user; expected " + rs.getOwner() + " got " + auth.getName()); + + // it wasn't issued to this user + m.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN); + return JsonErrorView.VIEWNAME; + } + + + for (Policy policy : rs.getPolicies()) { + if (policy.getId().equals(pid)) { + // found it! + rs.getPolicies().remove(policy); + resourceSetService.update(rs, rs); + + m.addAttribute(HttpCodeView.CODE, HttpStatus.NO_CONTENT); + return HttpCodeView.VIEWNAME; + } + } + + // if we made it this far, we haven't found it + m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND); + return HttpCodeView.VIEWNAME; + + } + +} From 1259b8cd688f1a7893b2ace6d1964f0623bfc7f3 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Thu, 2 Jul 2015 15:10:11 -0400 Subject: [PATCH 024/465] updated policy display --- uma-server-webapp/src/main/webapp/resources/js/policy.js | 9 +++++---- .../src/main/webapp/resources/template/policy.html | 8 +++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/uma-server-webapp/src/main/webapp/resources/js/policy.js b/uma-server-webapp/src/main/webapp/resources/js/policy.js index 49ecd61e14..b999a0809d 100644 --- a/uma-server-webapp/src/main/webapp/resources/js/policy.js +++ b/uma-server-webapp/src/main/webapp/resources/js/policy.js @@ -21,15 +21,16 @@ var ResourceSetModel = Backbone.Model.extend({ var ResourceSetCollection = Backbone.Collection.extend({ model: ResourceSetModel, - url: 'api/claims' + url: 'api/policy' }); -var ClaimModel = Backbone.Model.extend({ +var PolicyModel = Backbone.Model.extend({ }); -var ClaimCollection = Backbone.Collection.extend({ - model: ClaimModel +var PolicyCollection = Backbone.Collection.extend({ + model: PolicyModel, + baseUrl: 'api/policy' }); var ResourceSetListView = Backbone.View.extend({ diff --git a/uma-server-webapp/src/main/webapp/resources/template/policy.html b/uma-server-webapp/src/main/webapp/resources/template/policy.html index 17fd7bac8f..974bb2753c 100644 --- a/uma-server-webapp/src/main/webapp/resources/template/policy.html +++ b/uma-server-webapp/src/main/webapp/resources/template/policy.html @@ -48,11 +48,9 @@
Shared with: - <% if (!_.isEmpty(rs.claimsRequired)) { - _.each(rs.claimsRequired, function(claim) { %> - <%- claim.value %> - <% }); - } else { %> + <% if (!_.isEmpty(rs.policies)) { + %><%- _.size(rs.policies) %> + <% } else { %> NOBODY <% } %> From 72bb09550ce015aab8efbc406d33c6a21dd19be2 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Thu, 2 Jul 2015 16:20:03 -0400 Subject: [PATCH 025/465] basic display of Policy Table --- .../src/main/webapp/resources/js/admin.js | 10 ++- .../src/main/webapp/resources/js/policy.js | 63 +++++++++++++------ .../webapp/resources/template/policy.html | 46 +++++++++----- 3 files changed, 78 insertions(+), 41 deletions(-) diff --git a/uma-server-webapp/src/main/webapp/resources/js/admin.js b/uma-server-webapp/src/main/webapp/resources/js/admin.js index 98be97a2a2..93bddb6577 100644 --- a/uma-server-webapp/src/main/webapp/resources/js/admin.js +++ b/uma-server-webapp/src/main/webapp/resources/js/admin.js @@ -1109,16 +1109,14 @@ var AppRouter = Backbone.Router.extend({ var rs = this.resourceSetList.get(rsid); if (rs == null) { // need to load it directly - var claims = new ClaimCollection(); + var policy = new PolicyCollection([], {rsid: rsid}); } else { // the resource set is loaded, preload the claims - var claims = new ClaimCollection(rs.get('claimsRequired')); - claims.isFetched = true; + var policy = new PolicyCollection(rs.get('policies'), {rsid: rsid}); + policy.isFetched = true; } - // set the URL for the collection - claims.url = 'api/claims/' + rsid; - var view = new ClaimListView({model: claims, rs: rs}); + var view = new PolicyListView({model: policy, rs: rs}); view.load(function() { $('#content').html(view.render().el); diff --git a/uma-server-webapp/src/main/webapp/resources/js/policy.js b/uma-server-webapp/src/main/webapp/resources/js/policy.js index b999a0809d..8950413c4b 100644 --- a/uma-server-webapp/src/main/webapp/resources/js/policy.js +++ b/uma-server-webapp/src/main/webapp/resources/js/policy.js @@ -30,7 +30,12 @@ var PolicyModel = Backbone.Model.extend({ var PolicyCollection = Backbone.Collection.extend({ model: PolicyModel, - baseUrl: 'api/policy' + url: function() { + return 'api/policy/' + this.options.rsid; + }, + initialize: function(models, options) { + this.options = options; + } }); var ResourceSetListView = Backbone.View.extend({ @@ -228,7 +233,7 @@ var ResourceSetView = Backbone.View.extend({ }); -var ClaimListView = Backbone.View.extend({ +var PolicyListView = Backbone.View.extend({ tagName: 'span', initialize:function(options) { @@ -243,10 +248,10 @@ var ClaimListView = Backbone.View.extend({ $('#loadingbox').sheet('show'); $('#loading').html( - '' + $.t('policy.required-claims') + ' ' + '' + $.t('policy.loading-policies') + ' ' ); - $.when(this.model.fetchIfNeeded({success:function(e) {$('#loading-claims').addClass('label-success');}})) + $.when(this.model.fetchIfNeeded({success:function(e) {$('#loading-policies').addClass('label-success');}})) .done(function() { $('#loadingbox').sheet('hide'); callback(); @@ -256,7 +261,7 @@ var ClaimListView = Backbone.View.extend({ events:{ 'click .btn-save':'savePolicy', 'click .btn-cancel':'cancel', - 'click #add-email':'addClaim' + 'click #add-email':'addPolicy' }, cancel:function(e) { @@ -299,7 +304,7 @@ var ClaimListView = Backbone.View.extend({ }); }, - addClaim:function(e) { + addPolicy:function(e) { e.preventDefault(); // post to the webfinger helper and get the response back @@ -333,50 +338,50 @@ var ClaimListView = Backbone.View.extend({ togglePlaceholder:function() { if (this.model.length > 0) { - $('#required-claim-table', this.el).show(); - $('#required-claim-table-empty', this.el).hide(); + $('#policy-table', this.el).show(); + $('#policy-table-empty', this.el).hide(); } else { - $('#required-claim-table', this.el).hide(); - $('#required-claim-table-empty', this.el).show(); + $('#policy-table', this.el).hide(); + $('#policy-table-empty', this.el).show(); } }, render:function (eventName) { - $(this.el).html($('#tmpl-required-claim-table').html()); + $(this.el).html($('#tmpl-policy-table').html()); var _self = this; - _.each(this.model.models, function (claim) { + _.each(this.model.models, function (policy) { - var view = new ClaimView({model: claim}); + var view = new PolicyView({model: policy}); view.parentView = _self; - $('#required-claim-table', this.el).append(view.render().el); + $('#policy-table', this.el).append(view.render().el); }, this); this.togglePlaceholder(); - $(this.el).i18n(); + // $(this.el).i18n(); return this; } }); -var ClaimView = Backbone.View.extend({ +var PolicyView = Backbone.View.extend({ tagName: 'tr', initialize:function(options) { this.options = options; if (!this.template) { - this.template = _.template($('#tmpl-required-claim').html()); + this.template = _.template($('#tmpl-policy').html()); } }, events:{ - 'click .btn-remove':'removeClaim' + 'click .btn-remove':'removePolicy' }, - removeClaim:function(e) { + removePolicy:function(e) { e.preventDefault(); var _self = this; @@ -402,4 +407,24 @@ var ClaimView = Backbone.View.extend({ } +}); + + +var PolicyFormView = Backbone.View.extend({ + tagName: 'span', + + initialize:function(options) { + this.options = options; + + if (!this.template) { + this.template = _.template($('#tmpl-policy-form').html()); + } + }, + + render:function (eventName) { + + + + return this; + } }); \ No newline at end of file diff --git a/uma-server-webapp/src/main/webapp/resources/template/policy.html b/uma-server-webapp/src/main/webapp/resources/template/policy.html index 974bb2753c..f32dd2ff67 100644 --- a/uma-server-webapp/src/main/webapp/resources/template/policy.html +++ b/uma-server-webapp/src/main/webapp/resources/template/policy.html @@ -67,7 +67,7 @@ - - + + \ No newline at end of file From 03b301b43bef1c9a30ebbff3c1fe471ba9358a37 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 3 Jul 2015 09:21:24 -0400 Subject: [PATCH 029/465] moved policy API around, fixed render/loading in UI --- .../src/main/webapp/resources/js/admin.js | 8 ++-- .../src/main/webapp/resources/js/policy.js | 16 +++++--- .../webapp/resources/template/policy.html | 1 + .../java/org/mitre/uma/web/PolicyAPI.java | 41 ++++++++++++++++--- 4 files changed, 53 insertions(+), 13 deletions(-) diff --git a/uma-server-webapp/src/main/webapp/resources/js/admin.js b/uma-server-webapp/src/main/webapp/resources/js/admin.js index a23fe3fb99..3637b10913 100644 --- a/uma-server-webapp/src/main/webapp/resources/js/admin.js +++ b/uma-server-webapp/src/main/webapp/resources/js/admin.js @@ -1109,13 +1109,15 @@ var AppRouter = Backbone.Router.extend({ this.updateSidebar('user/policy'); var rs = this.resourceSetList.get(rsid); + var policies = null; if (rs == null) { // need to load it directly - var policies = new PolicyCollection([], {rsid: rsid}); + policies = new PolicyCollection([], {rsid: rsid}); + rs = new ResourceSetModel({id: rsid}); } else { // the resource set is loaded, preload the claims - var policies = new PolicyCollection(rs.get('policies'), {rsid: rsid}); - policy.isFetched = true; + policies = new PolicyCollection(rs.get('policies'), {rsid: rsid}); + policies.isFetched = true; } var view = new PolicyListView({model: policies, rs: rs, systemScopeList: this.systemScopeList}); diff --git a/uma-server-webapp/src/main/webapp/resources/js/policy.js b/uma-server-webapp/src/main/webapp/resources/js/policy.js index 7d56ef8d8f..1550aa0e6c 100644 --- a/uma-server-webapp/src/main/webapp/resources/js/policy.js +++ b/uma-server-webapp/src/main/webapp/resources/js/policy.js @@ -16,17 +16,17 @@ *******************************************************************************/ var ResourceSetModel = Backbone.Model.extend({ - + urlRoot: 'api/resourceset' }); var ResourceSetCollection = Backbone.Collection.extend({ model: ResourceSetModel, - url: 'api/policy' + url: 'api/resourceset' }); var PolicyModel = Backbone.Model.extend({ urlRoot: function() { - return 'api/policy/' + this.options.rsid + '/'; + return 'api/resourceset/' + this.options.rsid + '/policy/'; }, initialize: function(model, options) { this.options = options; @@ -36,7 +36,7 @@ var PolicyModel = Backbone.Model.extend({ var PolicyCollection = Backbone.Collection.extend({ model: PolicyModel, url: function() { - return 'api/policy/' + this.options.rsid; + return 'api/resourceset/' + this.options.rsid + '/policy/'; }, initialize: function(models, options) { this.options = options; @@ -352,6 +352,11 @@ var PolicyView = Backbone.View.extend({ this.template = _.template($('#tmpl-policy').html()); } + if (!this.scopeTemplate) { + this.scopeTemplate = _.template($('#tmpl-scope-list').html()); + } + + }, events:{ @@ -448,8 +453,9 @@ var PolicyFormView = Backbone.View.extend({ render:function (eventName) { var json = this.model.toJSON(); + var rs = this.options.rs.toJSON(); - this.$el.html(this.template({policy: json, rs: this.options.rs})); + this.$el.html(this.template({policy: json, rs: rs})); return this; } diff --git a/uma-server-webapp/src/main/webapp/resources/template/policy.html b/uma-server-webapp/src/main/webapp/resources/template/policy.html index 45b83a6aa8..a123200663 100644 --- a/uma-server-webapp/src/main/webapp/resources/template/policy.html +++ b/uma-server-webapp/src/main/webapp/resources/template/policy.html @@ -163,6 +163,7 @@

Edit Policy

+ <% console.log(rs); console.log(policy); %> <% _.each(rs.scopes, function(scope) { %>
Date: Fri, 3 Jul 2015 12:37:55 -0400 Subject: [PATCH 030/465] added edit policy button --- .../src/main/webapp/resources/js/policy.js | 12 ++++++++---- .../src/main/webapp/resources/template/policy.html | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/uma-server-webapp/src/main/webapp/resources/js/policy.js b/uma-server-webapp/src/main/webapp/resources/js/policy.js index 1550aa0e6c..56bd6df0bd 100644 --- a/uma-server-webapp/src/main/webapp/resources/js/policy.js +++ b/uma-server-webapp/src/main/webapp/resources/js/policy.js @@ -270,9 +270,7 @@ var PolicyListView = Backbone.View.extend({ }, events:{ - 'click .btn-save':'savePolicy', - 'click .btn-cancel':'cancel', - 'click #add-email':'addPolicy' + 'click .btn-cancel':'cancel' }, cancel:function(e) { @@ -329,7 +327,7 @@ var PolicyListView = Backbone.View.extend({ _.each(this.model.models, function (policy) { - var view = new PolicyView({model: policy, systemScopeList: _self.options.systemScopeList}); + var view = new PolicyView({model: policy, systemScopeList: _self.options.systemScopeList, rs: _self.options.rs}); view.parentView = _self; $('#policy-table', this.el).append(view.render().el); @@ -360,9 +358,15 @@ var PolicyView = Backbone.View.extend({ }, events:{ + 'click .btn-edit':'editPolicy', 'click .btn-remove':'removePolicy' }, + editPolicy:function(e) { + e.preventDefault(); + app.navigate('user/policy/' + this.options.rs.get("id") + '/' + this.model.get('id'), {trigger: true}); + }, + removePolicy:function(e) { e.preventDefault(); diff --git a/uma-server-webapp/src/main/webapp/resources/template/policy.html b/uma-server-webapp/src/main/webapp/resources/template/policy.html index a123200663..dbc409583a 100644 --- a/uma-server-webapp/src/main/webapp/resources/template/policy.html +++ b/uma-server-webapp/src/main/webapp/resources/template/policy.html @@ -129,6 +129,7 @@
+    
From f3a777a2c882057f022a17d40de5463347cfb978 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 3 Jul 2015 13:02:49 -0400 Subject: [PATCH 031/465] enabled scope editing on existing policies --- .../src/main/webapp/resources/js/admin.js | 4 +- .../src/main/webapp/resources/js/policy.js | 46 ++++++++++++++++++- .../webapp/resources/template/policy.html | 9 ++-- 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/uma-server-webapp/src/main/webapp/resources/js/admin.js b/uma-server-webapp/src/main/webapp/resources/js/admin.js index 3637b10913..fd2696e80a 100644 --- a/uma-server-webapp/src/main/webapp/resources/js/admin.js +++ b/uma-server-webapp/src/main/webapp/resources/js/admin.js @@ -1114,6 +1114,7 @@ var AppRouter = Backbone.Router.extend({ // need to load it directly policies = new PolicyCollection([], {rsid: rsid}); rs = new ResourceSetModel({id: rsid}); + this.resourceSetList.add(rs); // it will be loaded below, don't need to load it again in the future } else { // the resource set is loaded, preload the claims policies = new PolicyCollection(rs.get('policies'), {rsid: rsid}); @@ -1148,8 +1149,9 @@ var AppRouter = Backbone.Router.extend({ var policy = null; if (rs == null) { // need to load it directly - rs = new ResourceSetModel({id: rsid}); policy = new PolicyModel({id: pid}, {rsid: rsid}); + rs = new ResourceSetModel({id: rsid}); + this.resourceSetList.add(rs); // it will be loaded below, don't need to load it again in the future } else { // the resource set is loaded, preload the claims _.each(rs.get('policies'), function(p) { diff --git a/uma-server-webapp/src/main/webapp/resources/js/policy.js b/uma-server-webapp/src/main/webapp/resources/js/policy.js index 56bd6df0bd..c7d3af1558 100644 --- a/uma-server-webapp/src/main/webapp/resources/js/policy.js +++ b/uma-server-webapp/src/main/webapp/resources/js/policy.js @@ -419,7 +419,7 @@ var PolicyView = Backbone.View.extend({ var PolicyFormView = Backbone.View.extend({ - tagName: 'span', + tagName: 'div', initialize:function(options) { this.options = options; @@ -431,6 +431,10 @@ var PolicyFormView = Backbone.View.extend({ this.scopeCollection = new Backbone.Collection(); }, + events:{ + 'click .btn-save': 'savePolicy' + }, + load:function(callback) { if (this.model.isFetched && this.options.rs.isFetched && @@ -455,6 +459,46 @@ var PolicyFormView = Backbone.View.extend({ }); }, + savePolicy:function(e) { + e.preventDefault(); + + // get all the scopes that are checked + var scopes = $('#scopes input[type="checkbox"]:checked').map(function(idx, elem) { return $(elem).val(); }).get(); + + var valid = this.model.set({ + scopes: scopes + }); + + if (valid) { + + var _self = this; + this.model.save({}, { + success:function() { + app.systemScopeList.add(_self.model); + app.navigate('user/policy/' + _self.options.rs.get('id'), {trigger: true}); + }, + error:function(error, response) { + + //Pull out the response text. + var responseJson = JSON.parse(response.responseText); + + //Display an alert with an error message + $('#modalAlert div.modal-header').html(responseJson.error); + $('#modalAlert div.modal-body').html(responseJson.error_description); + + $("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog + "backdrop" : "static", + "keyboard" : true, + "show" : true // ensure the modal is shown immediately + }); + } + }); + } + + return false; + + }, + render:function (eventName) { var json = this.model.toJSON(); var rs = this.options.rs.toJSON(); diff --git a/uma-server-webapp/src/main/webapp/resources/template/policy.html b/uma-server-webapp/src/main/webapp/resources/template/policy.html index dbc409583a..262d90bda0 100644 --- a/uma-server-webapp/src/main/webapp/resources/template/policy.html +++ b/uma-server-webapp/src/main/webapp/resources/template/policy.html @@ -162,14 +162,13 @@

Edit Policy

- +
- <% console.log(rs); console.log(policy); %> <% _.each(rs.scopes, function(scope) { %>
- -1 ? 'checked' : '')%>> - + -1 ? 'checked' : '')%> value="<%- scope %>"> +
<% }); %>
From c5a65e9cec420498beb03081bf80d2f2faa19eae Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 3 Jul 2015 16:32:27 -0400 Subject: [PATCH 032/465] webfigner claims replacement works --- .../src/main/webapp/resources/js/policy.js | 77 +++++++++++-------- .../webapp/resources/template/policy.html | 12 +-- .../java/org/mitre/uma/web/PolicyAPI.java | 33 +++++++- .../mitre/uma/web/UserClaimSearchHelper.java | 59 ++++++++------ 4 files changed, 119 insertions(+), 62 deletions(-) diff --git a/uma-server-webapp/src/main/webapp/resources/js/policy.js b/uma-server-webapp/src/main/webapp/resources/js/policy.js index c7d3af1558..05fdcbdff3 100644 --- a/uma-server-webapp/src/main/webapp/resources/js/policy.js +++ b/uma-server-webapp/src/main/webapp/resources/js/policy.js @@ -278,43 +278,13 @@ var PolicyListView = Backbone.View.extend({ app.navigate('user/policy', {trigger: true}); }, - addPolicy:function(e) { - e.preventDefault(); - - // post to the webfinger helper and get the response back - - var _self = this; - - var email = $('#email', this.el).val(); - - var base = $('base').attr('href'); - $.getJSON(base + '/api/emailsearch?' + $.param({'identifier': email}), function(data) { - - var claim = new ClaimModel(data); - _self.model.add(claim, {'trigger': false}); - _self.render(); - - }).error(function(jqXHR, textStatus, errorThrown) { - console.log("An error occurred when doing a webfinger lookup", errorThrown); - - //Display an alert with an error message - $('#modalAlert div.modal-header').html($.t('policy.webfinger-error')); - $('#modalAlert div.modal-body').html($.t('policy.webfinger-error-description', {email: email})); - - $("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog - "backdrop" : "static", - "keyboard" : true, - "show" : true // ensure the modal is shown immediately - }); - }); - - }, - togglePlaceholder:function() { if (this.model.length > 0) { + $('#policy-info', this.el).show(); $('#policy-table', this.el).show(); $('#policy-table-empty', this.el).hide(); } else { + $('#policy-info', this.el).hide(); $('#policy-table', this.el).hide(); $('#policy-table-empty', this.el).show(); } @@ -432,7 +402,9 @@ var PolicyFormView = Backbone.View.extend({ }, events:{ - 'click .btn-save': 'savePolicy' + 'click .btn-share': 'addClaim', + 'click .btn-save': 'savePolicy', + 'click .btn-cancel': 'cancel' }, load:function(callback) { @@ -459,6 +431,40 @@ var PolicyFormView = Backbone.View.extend({ }); }, + addClaim:function(e) { + e.preventDefault(); + + // post to the webfinger helper and get the response back + + var _self = this; + + var email = $('#email', this.el).val(); + + var base = $('base').attr('href'); + $.getJSON(base + '/api/emailsearch?' + $.param({'identifier': email}), function(data) { + + _self.model.set({ + claimsRequired: data + }, {trigger: false}); + + _self.render(); + + }).error(function(jqXHR, textStatus, errorThrown) { + console.log("An error occurred when doing a webfinger lookup", errorThrown); + + //Display an alert with an error message + $('#modalAlert div.modal-header').html($.t('policy.webfinger-error')); + $('#modalAlert div.modal-body').html($.t('policy.webfinger-error-description', {email: email})); + + $("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog + "backdrop" : "static", + "keyboard" : true, + "show" : true // ensure the modal is shown immediately + }); + }); + + }, + savePolicy:function(e) { e.preventDefault(); @@ -499,6 +505,11 @@ var PolicyFormView = Backbone.View.extend({ }, + cancel:function(e) { + e.preventDefault(); + app.navigate('user/policy/' + this.options.rs.get('id'), {trigger: true}); + }, + render:function (eventName) { var json = this.model.toJSON(); var rs = this.options.rs.toJSON(); diff --git a/uma-server-webapp/src/main/webapp/resources/template/policy.html b/uma-server-webapp/src/main/webapp/resources/template/policy.html index 262d90bda0..b792d9a21b 100644 --- a/uma-server-webapp/src/main/webapp/resources/template/policy.html +++ b/uma-server-webapp/src/main/webapp/resources/template/policy.html @@ -60,7 +60,7 @@
-   +    
@@ -69,10 +69,10 @@ @@ -129,7 +129,7 @@
-   +    
@@ -153,7 +153,7 @@

Edit Policy

- +
diff --git a/uma-server/src/main/java/org/mitre/uma/web/PolicyAPI.java b/uma-server/src/main/java/org/mitre/uma/web/PolicyAPI.java index 7896c14279..4f3cdcbf1a 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/PolicyAPI.java +++ b/uma-server/src/main/java/org/mitre/uma/web/PolicyAPI.java @@ -85,7 +85,7 @@ public String getResourceSetsForCurrentUser(Model m, Authentication auth) { } /** - * List all the policies for the given resource set + * Get the indicated resource set * @param rsid * @param m * @param auth @@ -114,6 +114,37 @@ public String getResourceSet(@PathVariable (value = "rsid") Long rsid, Model m, return JsonEntityView.VIEWNAME; } + /** + * Delete the indicated resource set + * @param rsid + * @param m + * @param auth + * @return + */ + @RequestMapping(value = "/{rsid}", method = RequestMethod.DELETE, produces = MimeTypeUtils.APPLICATION_JSON_VALUE) + public String deleteResourceSet(@PathVariable (value = "rsid") Long rsid, Model m, Authentication auth) { + + ResourceSet rs = resourceSetService.getById(rsid); + + if (rs == null) { + m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND); + return HttpCodeView.VIEWNAME; + } + + if (!rs.getOwner().equals(auth.getName())) { + logger.warn("Unauthorized resource set request from bad user; expected " + rs.getOwner() + " got " + auth.getName()); + + // authenticated user didn't match the owner of the resource set + m.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN); + return HttpCodeView.VIEWNAME; + } + + resourceSetService.remove(rs); + m.addAttribute(HttpCodeView.CODE, HttpStatus.NO_CONTENT); + return HttpCodeView.VIEWNAME; + + } + /** * List all the policies for the given resource set * @param rsid diff --git a/uma-server/src/main/java/org/mitre/uma/web/UserClaimSearchHelper.java b/uma-server/src/main/java/org/mitre/uma/web/UserClaimSearchHelper.java index 41a3c7545d..7221a54325 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/UserClaimSearchHelper.java +++ b/uma-server/src/main/java/org/mitre/uma/web/UserClaimSearchHelper.java @@ -72,31 +72,46 @@ public String search(@RequestParam(value = "identifier") String email, Model m, UserInfo localUser = userInfoService.getByEmailAddress(email); if (localUser != null) { - Map entity = new HashMap<>(); - entity.put("issuer", ImmutableSet.of(config.getIssuer())); - entity.put("name", "email"); - entity.put("value", localUser.getEmail()); - - m.addAttribute(JsonEntityView.ENTITY, entity); + Map e = new HashMap<>(); + e.put("issuer", ImmutableSet.of(config.getIssuer())); + e.put("name", "email"); + e.put("value", localUser.getEmail()); + + Map ev = new HashMap<>(); + ev.put("issuer", ImmutableSet.of(config.getIssuer())); + ev.put("name", "email_verified"); + ev.put("value", localUser.getEmailVerified()); + + Map s = new HashMap<>(); + s.put("issuer", ImmutableSet.of(config.getIssuer())); + s.put("name", "sub"); + s.put("value", localUser.getSub()); + + m.addAttribute(JsonEntityView.ENTITY, ImmutableSet.of(e, ev, s)); return JsonEntityView.VIEWNAME; - } - - - // otherwise do a webfinger lookup - IssuerServiceResponse resp = webfingerIssuerService.getIssuer(req); + } else { - if (resp != null && resp.getIssuer() != null) { - // we found an issuer, return that - Map entity = new HashMap<>(); - entity.put("issuer", ImmutableSet.of(resp.getIssuer())); - entity.put("name", "email"); - entity.put("value", email); + // otherwise do a webfinger lookup + IssuerServiceResponse resp = webfingerIssuerService.getIssuer(req); - m.addAttribute(JsonEntityView.ENTITY, entity); - return JsonEntityView.VIEWNAME; - } else { - m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND); - return JsonErrorView.VIEWNAME; + if (resp != null && resp.getIssuer() != null) { + // we found an issuer, return that + Map e = new HashMap<>(); + e.put("issuer", ImmutableSet.of(resp.getIssuer())); + e.put("name", "email"); + e.put("value", email); + + Map ev = new HashMap<>(); + ev.put("issuer", ImmutableSet.of(resp.getIssuer())); + ev.put("name", "email_verified"); + ev.put("value", true); + + m.addAttribute(JsonEntityView.ENTITY, ImmutableSet.of(e, ev)); + return JsonEntityView.VIEWNAME; + } else { + m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND); + return JsonErrorView.VIEWNAME; + } } } From 214097584a467b543cf6526b4203506714088dda Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 3 Jul 2015 16:47:15 -0400 Subject: [PATCH 033/465] force refresh of resource set model after policies have been edited --- uma-server-webapp/src/main/webapp/resources/js/policy.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/uma-server-webapp/src/main/webapp/resources/js/policy.js b/uma-server-webapp/src/main/webapp/resources/js/policy.js index 05fdcbdff3..7c07fdcd2c 100644 --- a/uma-server-webapp/src/main/webapp/resources/js/policy.js +++ b/uma-server-webapp/src/main/webapp/resources/js/policy.js @@ -481,7 +481,12 @@ var PolicyFormView = Backbone.View.extend({ this.model.save({}, { success:function() { app.systemScopeList.add(_self.model); - app.navigate('user/policy/' + _self.options.rs.get('id'), {trigger: true}); + + // refresh the associated RS + _self.options.rs.fetch({success: function() { + app.navigate('user/policy/' + _self.options.rs.get('id'), {trigger: true}); + }}); + }, error:function(error, response) { From d4e36392365079aaca665873542792459818338c Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 3 Jul 2015 17:23:35 -0400 Subject: [PATCH 034/465] added "add new policy" controls --- .../src/main/webapp/resources/js/admin.js | 25 +++++++++++++++++++ .../src/main/webapp/resources/js/policy.js | 14 +++++++++-- .../webapp/resources/template/policy.html | 2 ++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/uma-server-webapp/src/main/webapp/resources/js/admin.js b/uma-server-webapp/src/main/webapp/resources/js/admin.js index fd2696e80a..e8eebaad41 100644 --- a/uma-server-webapp/src/main/webapp/resources/js/admin.js +++ b/uma-server-webapp/src/main/webapp/resources/js/admin.js @@ -506,6 +506,7 @@ var AppRouter = Backbone.Router.extend({ "user/policy":"policy", "user/policy/:rsid":"editPolicies", + "user/policy/:rsid/new":"newPolicy", "user/policy/:rsid/:pid":"editPolicy", "dev/dynreg":"dynReg", @@ -1131,7 +1132,31 @@ var AppRouter = Backbone.Router.extend({ }, newPolicy:function(rsid) { + this.breadCrumbView.collection.reset(); + this.breadCrumbView.collection.add([ + {text:$.t('admin.home'), href:""}, + {text:$.t('policy.resource-sets'), href:"manage/#user/policy"}, + {text:$.t('policy.edit-policies'), href:"manage/#user/policy/" + rsid}, + {text:$.t('policy.edit-policy'), href:"manage/#user/policy/" + rsid + "/new"} + ]); + + this.updateSidebar('user/policy'); + + var policy = policy = new PolicyModel({}, {rsid: rsid}); + + var rs = this.resourceSetList.get(rsid); + if (rs == null) { + // need to load it directly + rs = new ResourceSetModel({id: rsid}); + this.resourceSetList.add(rs); // it will be loaded below, don't need to load it again in the future + } + var view = new PolicyFormView({model: policy, rs: rs, systemScopeList: this.systemScopeList}); + + view.load(function() { + $('#content').html(view.render().el); + setPageTitle($.t('policy.edit-policy')); + }); }, editPolicy:function(rsid, pid) { diff --git a/uma-server-webapp/src/main/webapp/resources/js/policy.js b/uma-server-webapp/src/main/webapp/resources/js/policy.js index 7c07fdcd2c..952647720b 100644 --- a/uma-server-webapp/src/main/webapp/resources/js/policy.js +++ b/uma-server-webapp/src/main/webapp/resources/js/policy.js @@ -270,6 +270,7 @@ var PolicyListView = Backbone.View.extend({ }, events:{ + 'click .btn-add':'addPolicy', 'click .btn-cancel':'cancel' }, @@ -290,6 +291,11 @@ var PolicyListView = Backbone.View.extend({ } }, + addPolicy:function(e) { + e.preventDefault(); + app.navigate('user/policy/' + this.options.rs.get('id') +'/new', {trigger: true}); + }, + render:function (eventName) { $(this.el).html($('#tmpl-policy-table').html()); @@ -442,8 +448,12 @@ var PolicyFormView = Backbone.View.extend({ var base = $('base').attr('href'); $.getJSON(base + '/api/emailsearch?' + $.param({'identifier': email}), function(data) { - - _self.model.set({ + + // grab the current state of the scopes checkboxes just in case + var scopes = $('#scopes input[type="checkbox"]:checked').map(function(idx, elem) { return $(elem).val(); }).get(); + + _self.model.set({ + scopes: scopes, claimsRequired: data }, {trigger: false}); diff --git a/uma-server-webapp/src/main/webapp/resources/template/policy.html b/uma-server-webapp/src/main/webapp/resources/template/policy.html index b792d9a21b..48b859cfa8 100644 --- a/uma-server-webapp/src/main/webapp/resources/template/policy.html +++ b/uma-server-webapp/src/main/webapp/resources/template/policy.html @@ -69,6 +69,7 @@ - + \ No newline at end of file diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/user-context.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/user-context.xml index 62c49dcde3..89b4186241 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/user-context.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/user-context.xml @@ -37,10 +37,6 @@ - - - - @@ -52,6 +48,7 @@ + diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/login.jsp b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/login.jsp index 64b03d2f17..1d24457301 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/login.jsp +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/login.jsp @@ -26,8 +26,7 @@ $(document).ready(function() {
-
+
@@ -41,6 +40,7 @@ $(document).ready(function() {
+
From 3c222b0d79d359e969f4699223dd11b252432280 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 2 Oct 2015 18:37:57 -0400 Subject: [PATCH 090/465] rewrote blacklist UI, fixed delete functions on rest of UI, closes #905 --- .../src/main/webapp/WEB-INF/tags/footer.tag | 1 + .../src/main/webapp/resources/js/admin.js | 148 +------------ .../src/main/webapp/resources/js/blacklist.js | 195 ++++++++++++++++++ .../src/main/webapp/resources/js/client.js | 1 + .../src/main/webapp/resources/js/dynreg.js | 1 + .../src/main/webapp/resources/js/grant.js | 1 + .../src/main/webapp/resources/js/rsreg.js | 1 + .../src/main/webapp/resources/js/scope.js | 1 + .../src/main/webapp/resources/js/token.js | 2 + .../src/main/webapp/resources/js/whitelist.js | 1 + .../webapp/resources/template/blacklist.html | 69 +++++++ .../src/main/webapp/resources/js/admin.js | 3 +- .../src/main/webapp/resources/js/policy.js | 2 + 13 files changed, 285 insertions(+), 141 deletions(-) create mode 100644 openid-connect-server-webapp/src/main/webapp/resources/js/blacklist.js create mode 100644 openid-connect-server-webapp/src/main/webapp/resources/template/blacklist.html diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/tags/footer.tag b/openid-connect-server-webapp/src/main/webapp/WEB-INF/tags/footer.tag index a089cc2bbb..e1f35831f1 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/tags/footer.tag +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/tags/footer.tag @@ -30,6 +30,7 @@ + diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/admin.js b/openid-connect-server-webapp/src/main/webapp/resources/js/admin.js index 6951dde100..73ba1ce57d 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/admin.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/admin.js @@ -92,7 +92,8 @@ var ListWidgetChildView = Backbone.View.extend({ e.stopImmediatePropagation(); //this.$el.tooltip('delete'); - this.model.destroy({ + this.model.destroy({ + dataType: false, processData: false, error:function (error, response) { console.log("An error occurred when deleting from a list widget"); @@ -164,8 +165,6 @@ var ListWidgetView = Backbone.View.extend({ tagName: "div", - childView:ListWidgetChildView, - events:{ "click .btn-add-list-item":"addItem", "keypress":function (e) { @@ -225,7 +224,7 @@ var ListWidgetView = Backbone.View.extend({ this.$el.html(this.template({placeholder:this.options.placeholder, helpBlockText:this.options.helpBlockText})); - _self = this; + var _self = this; if (_.size(this.collection.models) == 0 && _.size(this.options.autocomplete) == 0) { $("tbody", _self.el).html($('#tmpl-list-widget-child-empty').html()); @@ -255,7 +254,7 @@ var ListWidgetView = Backbone.View.extend({ checked = false; } - var el = new this.childView({model:model, toggle: true, checked: checked, collection: _self.collection}).render().el; + var el = new ListWidgetChildView({model:model, toggle: true, checked: checked, collection: _self.collection}).render().el; $("tbody", _self.el).append(el); }, this); @@ -264,8 +263,7 @@ var ListWidgetView = Backbone.View.extend({ // now render everything not in the autocomplete list _.each(values.models, function (model) { - - var el = new this.childView({model:model, collection: _self.collection}).render().el; + var el = new ListWidgetChildView({model:model, collection: _self.collection}).render().el; $("tbody", _self.el).append(el); }, this); } @@ -276,18 +274,6 @@ var ListWidgetView = Backbone.View.extend({ }); -var BlackListModel = Backbone.Model.extend({ - idAttribute: 'id', - - urlRoot: 'api/blacklist' -}); - -var BlackListCollection = Backbone.Collection.extend({ - initialize: function() { }, - - url: "api/blacklist" -}); - var BreadCrumbView = Backbone.View.extend({ tagName: 'ul', @@ -328,125 +314,6 @@ var BreadCrumbView = Backbone.View.extend({ }); -var BlackListListView = Backbone.View.extend({ - tagName: 'span', - - initialize:function(options) { - this.options = options; - if (!this.template) { - this.template = _.template($('#tmpl-blacklist-form').html()); - } - }, - - load:function(callback) { - if (this.model.isFetched) { - callback(); - return; - } - - $('#loadingbox').sheet('show'); - $('#loading').html( - '' + $.t('admin.blacklist') + ' ' - ); - - $.when(this.model.fetchIfNeeded()).done(function() { - $('#loading-blacklist').addClass('label-success'); - $('#loadingbox').sheet('hide'); - callback(); - }); - }, - - events: { - "click .refresh-table":"refreshTable" - }, - - refreshTable:function(e) { - e.preventDefault(); - var _self = this; - $('#loadingbox').sheet('show'); - $('#loading').html( - '' + $.t('admin.blacklist') + ' ' - ); - - $.when(this.model.fetch()).done(function() { - $('#loadingbox').sheet('hide'); - _self.render(); - }); - }, - - render:function (eventName) { - - $(this.el).html(this.template(this.model.toJSON())); - - $('#blacklist .controls', this.el).html(new BlackListWidgetView({ - type: 'uri', - placeholder: 'http://', - collection: this.model - }).render().el); - - $(this.el).i18n(); - return this; - } -}); - -var BlackListWidgetView = ListWidgetView.extend({ - - childView: ListWidgetChildView.extend({ - render:function(options) { - this.options = options; - var uri = this.model.get('uri'); - - this.$el.html(this.template({item: uri})); - - if (uri.length > 30) { - this.$el.tooltip({title:uri}); - } - return this; - - } - }), - - addItem:function(e) { - e.preventDefault(); - - var input_value = $("input", this.el).val().trim(); - - if (input_value === "") { - return; - } - - // TODO: URI/pattern validation, check against existing clients - - var item = new BlackListModel({ - uri: input_value - }); - - var _self = this; // closures... - - item.save({}, { - success:function() { - _self.collection.add(item); - }, - error:function(error, response) { - //Pull out the response text. - var responseJson = JSON.parse(response.responseText); - - //Display an alert with an error message - $('#modalAlert div.modal-header').html(responseJson.error); - $('#modalAlert div.modal-body').html(responseJson.error_description); - - $("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog - "backdrop" : "static", - "keyboard" : true, - "show" : true // ensure the modal is shown immediately - }); - } - }); - - } - -}); - // Stats table var StatsModel = Backbone.Model.extend({ @@ -856,7 +723,7 @@ var AppRouter = Backbone.Router.extend({ this.updateSidebar('admin/blacklist'); - var view = new BlackListListView({model:this.blackListList}); + var view = new BlackListListView({collection: this.blackListList}); view.load( function(collection, response, options) { @@ -1129,7 +996,8 @@ $(function () { $.get('resources/template/whitelist.html', _load), $.get('resources/template/dynreg.html', _load), $.get('resources/template/rsreg.html', _load), - $.get('resources/template/token.html', _load) + $.get('resources/template/token.html', _load), + $.get('resources/template/blacklist.html', _load) ).done(function() { $.ajaxSetup({cache:false}); app = new AppRouter(); diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/blacklist.js b/openid-connect-server-webapp/src/main/webapp/resources/js/blacklist.js new file mode 100644 index 0000000000..0e0b5e7efa --- /dev/null +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/blacklist.js @@ -0,0 +1,195 @@ +var BlackListModel = Backbone.Model.extend({ + idAttribute: 'id', + + urlRoot: 'api/blacklist' +}); + +var BlackListCollection = Backbone.Collection.extend({ + initialize: function() { }, + + url: "api/blacklist" +}); + +var BlackListListView = Backbone.View.extend({ + tagName: 'span', + + initialize:function(options) { + this.options = options; + }, + + load:function(callback) { + if (this.collection.isFetched) { + callback(); + return; + } + + $('#loadingbox').sheet('show'); + $('#loading').html( + '' + $.t('admin.blacklist') + ' ' + ); + + $.when(this.collection.fetchIfNeeded({success:function(e) {$('#loading-blacklist').addClass('label-success');}})) + .done(function() { + $('#loadingbox').sheet('hide'); + callback(); + }); + }, + + events: { + "click .refresh-table":"refreshTable", + "click .btn-add":"addItem", + "submit #add-blacklist form":"addItem" + }, + + refreshTable:function(e) { + e.preventDefault(); + + var _self = this; + $('#loadingbox').sheet('show'); + $('#loading').html( + '' + $.t('admin.blacklist') + ' ' + ); + + $.when(this.collection.fetch()).done(function() { + $('#loadingbox').sheet('hide'); + _self.render(); + }); + }, + + togglePlaceholder:function() { + if (this.collection.length > 0) { + $('#blacklist-table', this.el).show(); + $('#blacklist-table-empty', this.el).hide(); + } else { + $('#blacklist-table', this.el).hide(); + $('#blacklist-table-empty', this.el).show(); + } + }, + + render:function (eventName) { + + $(this.el).html($('#tmpl-blacklist-table').html()); + + var _self = this; + _.each(this.collection.models, function(blacklist) { + var view = new BlackListWidgetView({model: blacklist}); + view.parentView = _self; + $("#blacklist-table", _self.el).append(view.render().el); + }, this); + + this.togglePlaceholder(); + + $(this.el).i18n(); + return this; + }, + + addItem:function(e) { + e.preventDefault(); + + var input_value = $("#blacklist-uri", this.el).val().trim(); + + if (input_value === "") { + return; + } + + // TODO: URI/pattern validation, check against existing clients + + var item = new BlackListModel({ + uri: input_value + }); + + var _self = this; // closures... + + item.save({}, { + success:function() { + _self.collection.add(item); + _self.render(); + }, + error:function(error, response) { + //Pull out the response text. + var responseJson = JSON.parse(response.responseText); + + //Display an alert with an error message + $('#modalAlert div.modal-header').html(responseJson.error); + $('#modalAlert div.modal-body').html(responseJson.error_description); + + $("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog + "backdrop" : "static", + "keyboard" : true, + "show" : true // ensure the modal is shown immediately + }); + } + }); + + } + +}); + +var BlackListWidgetView = Backbone.View.extend({ + + tagName: 'tr', + + initialize:function(options) { + this.options = options; + + if (!this.template) { + this.template = _.template($('#tmpl-blacklist-item').html()); + } + }, + + render:function() { + + this.$el.html(this.template(this.model.toJSON())); + + return this; + + }, + + events:{ + 'click .btn-delete':'deleteBlacklist' + }, + + deleteBlacklist:function (e) { + e.preventDefault(); + + if (confirm($.t("blacklist.confirm"))) { + var _self = this; + + this.model.destroy({ + dataType: false, processData: false, + success:function () { + + _self.$el.fadeTo("fast", 0.00, function () { //fade + $(this).slideUp("fast", function () { //slide up + $(this).remove(); //then remove from the DOM + _self.parentView.togglePlaceholder(); + }); + }); + }, + error:function (model, response) { + //Pull out the response text. + var responseJson = {error: 'Error', error_description: 'Error.'}; + if (response) { + responseJson = JSON.parse(response.responseText); + } + + //Display an alert with an error message + $('#modalAlert div.modal-header').html(responseJson.error); + $('#modalAlert div.modal-body').html(responseJson.error_description); + + $("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog + "backdrop" : "static", + "keyboard" : true, + "show" : true // ensure the modal is shown immediately + }); + } + }); + + _self.parentView.delegateEvents(); + } + + return false; + } + +}); + diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/client.js b/openid-connect-server-webapp/src/main/webapp/resources/js/client.js index a892d52078..8d5633e560 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/client.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/client.js @@ -363,6 +363,7 @@ var ClientView = Backbone.View.extend({ var _self = this; this.model.destroy({ + dataType: false, processData: false, success:function () { _self.$el.fadeTo("fast", 0.00, function () { //fade $(this).slideUp("fast", function () { //slide up diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/dynreg.js b/openid-connect-server-webapp/src/main/webapp/resources/js/dynreg.js index c17e3e465e..10aa99dd79 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/dynreg.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/dynreg.js @@ -232,6 +232,7 @@ var DynRegEditView = Backbone.View.extend({ var self = this; this.model.destroy({ + dataType: false, processData: false, success:function () { self.remove(); app.navigate('dev/dynreg', {trigger: true}); diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/grant.js b/openid-connect-server-webapp/src/main/webapp/resources/js/grant.js index 9fa1cdf11c..e42a053ce8 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/grant.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/grant.js @@ -218,6 +218,7 @@ var ApprovedSiteView = Backbone.View.extend({ var self = this; this.model.destroy({ + dataType: false, processData: false, success:function () { self.$el.fadeTo("fast", 0.00, function () { //fade $(this).slideUp("fast", function () { //slide up diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/rsreg.js b/openid-connect-server-webapp/src/main/webapp/resources/js/rsreg.js index 4382c3347f..b8f95cb8de 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/rsreg.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/rsreg.js @@ -197,6 +197,7 @@ var ResRegEditView = Backbone.View.extend({ var self = this; this.model.destroy({ + dataType: false, processData: false, success:function () { self.remove(); app.navigate('dev/resource', {trigger: true}); diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/scope.js b/openid-connect-server-webapp/src/main/webapp/resources/js/scope.js index a8ebfef516..c4dcb83df0 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/scope.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/scope.js @@ -113,6 +113,7 @@ var SystemScopeView = Backbone.View.extend({ var _self = this; this.model.destroy({ + dataType: false, processData: false, success:function () { _self.$el.fadeTo("fast", 0.00, function () { //fade diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/token.js b/openid-connect-server-webapp/src/main/webapp/resources/js/token.js index 74d9beacc8..c04a16e092 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/token.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/token.js @@ -106,6 +106,7 @@ var AccessTokenView = Backbone.View.extend({ var _self = this; this.model.destroy({ + dataType: false, processData: false, success:function () { _self.$el.fadeTo("fast", 0.00, function () { //fade @@ -257,6 +258,7 @@ var RefreshTokenView = Backbone.View.extend({ var _self = this; this.model.destroy({ + dataType: false, processData: false, success:function () { _self.$el.fadeTo("fast", 0.00, function () { //fade diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/whitelist.js b/openid-connect-server-webapp/src/main/webapp/resources/js/whitelist.js index 965da262ec..39c0bdd208 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/whitelist.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/whitelist.js @@ -186,6 +186,7 @@ var WhiteListView = Backbone.View.extend({ var _self = this; this.model.destroy({ + dataType: false, processData: false, success:function () { _self.$el.fadeTo("fast", 0.00, function () { //fade $(this).slideUp("fast", function () { //slide up diff --git a/openid-connect-server-webapp/src/main/webapp/resources/template/blacklist.html b/openid-connect-server-webapp/src/main/webapp/resources/template/blacklist.html new file mode 100644 index 0000000000..0ed9585f09 --- /dev/null +++ b/openid-connect-server-webapp/src/main/webapp/resources/template/blacklist.html @@ -0,0 +1,69 @@ + + + + + diff --git a/uma-server-webapp/src/main/webapp/resources/js/admin.js b/uma-server-webapp/src/main/webapp/resources/js/admin.js index f6cc186f6a..165e0c080e 100644 --- a/uma-server-webapp/src/main/webapp/resources/js/admin.js +++ b/uma-server-webapp/src/main/webapp/resources/js/admin.js @@ -92,7 +92,8 @@ var ListWidgetChildView = Backbone.View.extend({ e.stopImmediatePropagation(); //this.$el.tooltip('delete'); - this.model.destroy({ + this.model.destroy({ + dataType: false, processData: false, error:function (error, response) { console.log("An error occurred when deleting from a list widget"); diff --git a/uma-server-webapp/src/main/webapp/resources/js/policy.js b/uma-server-webapp/src/main/webapp/resources/js/policy.js index 83ed99b9c4..966da884cb 100644 --- a/uma-server-webapp/src/main/webapp/resources/js/policy.js +++ b/uma-server-webapp/src/main/webapp/resources/js/policy.js @@ -187,6 +187,7 @@ var ResourceSetView = Backbone.View.extend({ var _self = this; this.model.destroy({ + dataType: false, processData: false, success:function () { _self.$el.fadeTo("fast", 0.00, function () { //fade $(this).slideUp("fast", function () { //slide up @@ -349,6 +350,7 @@ var PolicyView = Backbone.View.extend({ if (confirm($.t('policy.policy-table.confirm'))) { var _self = this; this.model.destroy({ + dataType: false, processData: false, success:function () { _self.$el.fadeTo("fast", 0.00, function () { //fade $(this).slideUp("fast", function () { //slide up From 4063f7f94f23e00370b6193d08372187d094111e Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 2 Oct 2015 18:48:11 -0400 Subject: [PATCH 091/465] user info endpoint response uses correct client algorithms, addresses #921 --- .../java/org/mitre/openid/connect/view/UserInfoJWTView.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoJWTView.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoJWTView.java index 5a57d271d8..027ff0933b 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoJWTView.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoJWTView.java @@ -109,8 +109,8 @@ protected void writeOut(JsonObject json, Map model, claims.setJWTID(UUID.randomUUID().toString()); // set a random NONCE in the middle of it - if (client.getIdTokenEncryptedResponseAlg() != null && !client.getIdTokenEncryptedResponseAlg().equals(Algorithm.NONE) - && client.getIdTokenEncryptedResponseEnc() != null && !client.getIdTokenEncryptedResponseEnc().equals(Algorithm.NONE) + if (client.getUserInfoEncryptedResponseAlg() != null && !client.getUserInfoEncryptedResponseAlg().equals(Algorithm.NONE) + && client.getUserInfoEncryptedResponseEnc() != null && !client.getUserInfoEncryptedResponseEnc().equals(Algorithm.NONE) && (!Strings.isNullOrEmpty(client.getJwksUri()) || client.getJwks() != null)) { // encrypt it to the client's key @@ -119,7 +119,7 @@ protected void writeOut(JsonObject json, Map model, if (encrypter != null) { - EncryptedJWT encrypted = new EncryptedJWT(new JWEHeader(client.getIdTokenEncryptedResponseAlg(), client.getIdTokenEncryptedResponseEnc()), claims); + EncryptedJWT encrypted = new EncryptedJWT(new JWEHeader(client.getUserInfoEncryptedResponseAlg(), client.getUserInfoEncryptedResponseEnc()), claims); encrypter.encryptJwt(encrypted); From e384a6257b9baad692e616826528012d4f04dadc Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 2 Oct 2015 18:53:45 -0400 Subject: [PATCH 092/465] [maven-release-plugin] prepare release mitreid-connect-1.2.1 --- openid-connect-client/pom.xml | 2 +- openid-connect-common/pom.xml | 2 +- openid-connect-server-webapp/pom.xml | 2 +- openid-connect-server/pom.xml | 2 +- pom.xml | 2 +- uma-server-webapp/pom.xml | 2 +- uma-server/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/openid-connect-client/pom.xml b/openid-connect-client/pom.xml index a6d191b410..38698ac275 100644 --- a/openid-connect-client/pom.xml +++ b/openid-connect-client/pom.xml @@ -21,7 +21,7 @@ openid-connect-parent org.mitre - 1.2.1-SNAPSHOT + 1.2.1 .. openid-connect-client diff --git a/openid-connect-common/pom.xml b/openid-connect-common/pom.xml index 408d626641..46951c7d44 100644 --- a/openid-connect-common/pom.xml +++ b/openid-connect-common/pom.xml @@ -21,7 +21,7 @@ openid-connect-parent org.mitre - 1.2.1-SNAPSHOT + 1.2.1 .. openid-connect-common diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index d628f7d32f..ad89464c48 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.2.1-SNAPSHOT + 1.2.1 openid-connect-server-webapp war diff --git a/openid-connect-server/pom.xml b/openid-connect-server/pom.xml index 444ee036f8..a1753f62f4 100644 --- a/openid-connect-server/pom.xml +++ b/openid-connect-server/pom.xml @@ -22,7 +22,7 @@ org.mitre openid-connect-parent - 1.2.1-SNAPSHOT + 1.2.1 .. diff --git a/pom.xml b/pom.xml index 6fe8a69b07..b947da43c1 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ 4.0.0 org.mitre openid-connect-parent - 1.2.1-SNAPSHOT + 1.2.1 MITREid Connect pom diff --git a/uma-server-webapp/pom.xml b/uma-server-webapp/pom.xml index 9f5da0bd5a..48db852535 100644 --- a/uma-server-webapp/pom.xml +++ b/uma-server-webapp/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.2.1-SNAPSHOT + 1.2.1 .. uma-server-webapp diff --git a/uma-server/pom.xml b/uma-server/pom.xml index 5f5c43c286..54642c3b3b 100644 --- a/uma-server/pom.xml +++ b/uma-server/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.2.1-SNAPSHOT + 1.2.1 .. uma-server From 8b362f23f350e93c418126cf18929e6266f69515 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 2 Oct 2015 18:53:48 -0400 Subject: [PATCH 093/465] [maven-release-plugin] prepare for next development iteration --- openid-connect-client/pom.xml | 2 +- openid-connect-common/pom.xml | 2 +- openid-connect-server-webapp/pom.xml | 2 +- openid-connect-server/pom.xml | 2 +- pom.xml | 2 +- uma-server-webapp/pom.xml | 2 +- uma-server/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/openid-connect-client/pom.xml b/openid-connect-client/pom.xml index 38698ac275..67f4a39c12 100644 --- a/openid-connect-client/pom.xml +++ b/openid-connect-client/pom.xml @@ -21,7 +21,7 @@ openid-connect-parent org.mitre - 1.2.1 + 1.2.2-SNAPSHOT .. openid-connect-client diff --git a/openid-connect-common/pom.xml b/openid-connect-common/pom.xml index 46951c7d44..7156af5f06 100644 --- a/openid-connect-common/pom.xml +++ b/openid-connect-common/pom.xml @@ -21,7 +21,7 @@ openid-connect-parent org.mitre - 1.2.1 + 1.2.2-SNAPSHOT .. openid-connect-common diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index ad89464c48..166e5fb6c9 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.2.1 + 1.2.2-SNAPSHOT openid-connect-server-webapp war diff --git a/openid-connect-server/pom.xml b/openid-connect-server/pom.xml index a1753f62f4..ccd914b9ed 100644 --- a/openid-connect-server/pom.xml +++ b/openid-connect-server/pom.xml @@ -22,7 +22,7 @@ org.mitre openid-connect-parent - 1.2.1 + 1.2.2-SNAPSHOT .. diff --git a/pom.xml b/pom.xml index b947da43c1..ced2485ee6 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ 4.0.0 org.mitre openid-connect-parent - 1.2.1 + 1.2.2-SNAPSHOT MITREid Connect pom diff --git a/uma-server-webapp/pom.xml b/uma-server-webapp/pom.xml index 48db852535..52d3c6323e 100644 --- a/uma-server-webapp/pom.xml +++ b/uma-server-webapp/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.2.1 + 1.2.2-SNAPSHOT .. uma-server-webapp diff --git a/uma-server/pom.xml b/uma-server/pom.xml index 54642c3b3b..de381d9570 100644 --- a/uma-server/pom.xml +++ b/uma-server/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.2.1 + 1.2.2-SNAPSHOT .. uma-server From b5c298e0caf76012bda186e36e4eca0c910b9e38 Mon Sep 17 00:00:00 2001 From: Mark Janssen Date: Fri, 9 Oct 2015 00:24:38 +0200 Subject: [PATCH 094/465] Remove legacy CSRF protection for approve page Instead, we rely on the Spring Security CSRF protection, like we already do for the login page. Additionally, we remove the authentication check in`isApproved`, because this is already done by Spring Security (and if not, we have bigger problems to worry about). --- .../src/main/webapp/WEB-INF/views/approve.jsp | 4 ++-- .../web/OAuthConfirmationController.java | 4 ---- .../request/ConnectOAuth2RequestFactory.java | 8 ------- .../request/ConnectRequestParameters.java | 1 - .../token/TofuUserApprovalHandler.java | 22 +++---------------- 5 files changed, 5 insertions(+), 34 deletions(-) diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/approve.jsp b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/approve.jsp index 80385cc35c..a42826a967 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/approve.jsp +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/approve.jsp @@ -260,8 +260,8 @@ - - + +   diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java index 895cae1335..b97aa1d6ee 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java @@ -57,7 +57,6 @@ import com.google.common.collect.Sets; import com.google.gson.JsonObject; -import static org.mitre.openid.connect.request.ConnectRequestParameters.CSRF; import static org.mitre.openid.connect.request.ConnectRequestParameters.PROMPT; import static org.mitre.openid.connect.request.ConnectRequestParameters.PROMPT_SEPARATOR; @@ -221,9 +220,6 @@ public String confimAccess(Map model, @ModelAttribute("authoriza model.put("gras", false); } - // inject a random value for CSRF purposes - model.put("csrf", authRequest.getExtensions().get(CSRF)); - return "approve"; } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectOAuth2RequestFactory.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectOAuth2RequestFactory.java index 74e843d5cb..62a23d41cb 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectOAuth2RequestFactory.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectOAuth2RequestFactory.java @@ -55,7 +55,6 @@ import static org.mitre.openid.connect.request.ConnectRequestParameters.CLAIMS; import static org.mitre.openid.connect.request.ConnectRequestParameters.CLIENT_ID; -import static org.mitre.openid.connect.request.ConnectRequestParameters.CSRF; import static org.mitre.openid.connect.request.ConnectRequestParameters.DISPLAY; import static org.mitre.openid.connect.request.ConnectRequestParameters.LOGIN_HINT; import static org.mitre.openid.connect.request.ConnectRequestParameters.MAX_AGE; @@ -157,13 +156,6 @@ public AuthorizationRequest createAuthorizationRequest(Map input } } - - // add CSRF protection to the request on first parse - String csrf = UUID.randomUUID().toString(); - request.getExtensions().put(CSRF, csrf); - - - return request; } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectRequestParameters.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectRequestParameters.java index 81def22be6..6e38af8fc0 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectRequestParameters.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectRequestParameters.java @@ -38,7 +38,6 @@ public interface ConnectRequestParameters { public String PROMPT_SEPARATOR = " "; // extensions - public String CSRF = "csrf"; public String APPROVED_SITE = "approved_site"; // responses diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/TofuUserApprovalHandler.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/TofuUserApprovalHandler.java index 99968536f5..bda563654e 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/TofuUserApprovalHandler.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/TofuUserApprovalHandler.java @@ -48,7 +48,6 @@ import com.google.common.collect.Sets; import static org.mitre.openid.connect.request.ConnectRequestParameters.APPROVED_SITE; -import static org.mitre.openid.connect.request.ConnectRequestParameters.CSRF; import static org.mitre.openid.connect.request.ConnectRequestParameters.PROMPT; import static org.mitre.openid.connect.request.ConnectRequestParameters.PROMPT_SEPARATOR; @@ -102,21 +101,8 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat return true; } else { // if not, check to see if the user has approved it - if (Boolean.parseBoolean(authorizationRequest.getApprovalParameters().get("user_oauth_approval"))) { // TODO: make parameter name configurable? - - // check the value of the CSRF parameter - - if (authorizationRequest.getExtensions().get(CSRF) != null) { - if (authorizationRequest.getExtensions().get(CSRF).equals(authorizationRequest.getApprovalParameters().get(CSRF))) { - - // make sure the user is actually authenticated - return userAuthentication.isAuthenticated(); - } - } - } - - // if the above doesn't pass, it's not yet approved - return false; + // TODO: make parameter name configurable? + return Boolean.parseBoolean(authorizationRequest.getApprovalParameters().get("user_oauth_approval")); } } @@ -195,9 +181,7 @@ public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizati ClientDetails client = clientDetailsService.loadClientByClientId(clientId); // This must be re-parsed here because SECOAUTH forces us to call things in a strange order - if (Boolean.parseBoolean(authorizationRequest.getApprovalParameters().get("user_oauth_approval")) - && authorizationRequest.getExtensions().get(CSRF) != null - && authorizationRequest.getExtensions().get(CSRF).equals(authorizationRequest.getApprovalParameters().get(CSRF))) { + if (Boolean.parseBoolean(authorizationRequest.getApprovalParameters().get("user_oauth_approval"))) { authorizationRequest.setApproved(true); From 58543ac9c4bd53ee442ddb36636db5fa26e2c60e Mon Sep 17 00:00:00 2001 From: Mark Janssen Date: Sun, 11 Oct 2015 23:48:37 +0200 Subject: [PATCH 095/465] Fix ID token icon description --- .../src/main/webapp/resources/template/token.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openid-connect-server-webapp/src/main/webapp/resources/template/token.html b/openid-connect-server-webapp/src/main/webapp/resources/template/token.html index 8ce239a1e0..9bef2ef4c0 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/template/token.html +++ b/openid-connect-server-webapp/src/main/webapp/resources/template/token.html @@ -100,7 +100,7 @@ <% } %> <% if (token.idTokenId != null) { %>
- + ID + + ID <% } %> From 7871ee0f2603b98131c618a2729052b2da40c89f Mon Sep 17 00:00:00 2001 From: Mark Janssen Date: Thu, 8 Oct 2015 23:59:54 +0200 Subject: [PATCH 096/465] Improve error message --- .../src/main/webapp/WEB-INF/views/error.jsp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/error.jsp b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/error.jsp index ce2d373e3d..5410c1efeb 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/error.jsp +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/error.jsp @@ -16,8 +16,8 @@ if (request.getAttribute("error") != null && request.getAttribute("error") insta } else if (request.getAttribute("javax.servlet.error.status_code") != null) { Integer code = (Integer)request.getAttribute("javax.servlet.error.status_code"); HttpStatus status = HttpStatus.valueOf(code); - request.setAttribute("errorCode", status.toString()); - request.setAttribute("message", status.getReasonPhrase()); + request.setAttribute("errorCode", status.toString() + " " + status.getReasonPhrase()); + request.setAttribute("message", request.getAttribute("javax.servlet.error.message")); } else { request.setAttribute("errorCode", "Server error"); request.setAttribute("message", "See the logs for details"); From 0269c24263adeeeb77199c7567091e012cc8ea52 Mon Sep 17 00:00:00 2001 From: Mark Janssen Date: Sun, 4 Oct 2015 16:19:39 +0200 Subject: [PATCH 097/465] Travis build on JDK 7+8 Configures Travis to build on Oracle JDK 7+8 and OpenJDK 7. Also enables migration to Travis' container-based infrastructure: http://docs.travis-ci.com/user/migrating-from-legacy/ --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index dff5f3a5d0..3be2ae5cdf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1 +1,6 @@ language: java +jdk: + - oraclejdk8 + - oraclejdk7 + - openjdk7 +sudo: false From 9117e7fe31363fa0991d89a154e5032ca5d17507 Mon Sep 17 00:00:00 2001 From: Mark Janssen Date: Sun, 4 Oct 2015 16:15:36 +0200 Subject: [PATCH 098/465] Add SQL indexes for PostgreSQL and HSQLDB --- .../src/main/resources/db/tables/hsql_database_tables.sql | 7 +++++++ .../src/main/resources/db/tables/psql_database_tables.sql | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/openid-connect-server-webapp/src/main/resources/db/tables/hsql_database_tables.sql b/openid-connect-server-webapp/src/main/resources/db/tables/hsql_database_tables.sql index dac2a94327..69e74508cb 100644 --- a/openid-connect-server-webapp/src/main/resources/db/tables/hsql_database_tables.sql +++ b/openid-connect-server-webapp/src/main/resources/db/tables/hsql_database_tables.sql @@ -356,3 +356,10 @@ CREATE TABLE IF NOT EXISTS saved_registered_client ( issuer VARCHAR(1024), registered_client VARCHAR(8192) ); + + +CREATE INDEX at_tv_idx ON access_token(token_value); +CREATE INDEX ts_oi_idx ON token_scope(owner_id); +CREATE INDEX at_exp_idx ON access_token(expiration); +CREATE INDEX rf_ahi_idx ON refresh_token(auth_holder_id); +CREATE INDEX cd_ci_idx ON client_details(client_id); \ No newline at end of file diff --git a/openid-connect-server-webapp/src/main/resources/db/tables/psql_database_tables.sql b/openid-connect-server-webapp/src/main/resources/db/tables/psql_database_tables.sql index 63462a171b..da7e697671 100644 --- a/openid-connect-server-webapp/src/main/resources/db/tables/psql_database_tables.sql +++ b/openid-connect-server-webapp/src/main/resources/db/tables/psql_database_tables.sql @@ -356,3 +356,10 @@ CREATE TABLE IF NOT EXISTS saved_registered_client ( issuer VARCHAR(1024), registered_client VARCHAR(8192) ); + + +CREATE INDEX at_tv_idx ON access_token(token_value); +CREATE INDEX ts_oi_idx ON token_scope(owner_id); +CREATE INDEX at_exp_idx ON access_token(expiration); +CREATE INDEX rf_ahi_idx ON refresh_token(auth_holder_id); +CREATE INDEX cd_ci_idx ON client_details(client_id); \ No newline at end of file From 8b7fc5de682f70c86bc70d5c2f37b0e6a76ca9f4 Mon Sep 17 00:00:00 2001 From: Mark Janssen Date: Sun, 4 Oct 2015 15:38:27 +0200 Subject: [PATCH 099/465] Update HikariCP to 2.4.1 https://github.com/brettwooldridge/HikariCP/blob/dev/CHANGES --- openid-connect-server-webapp/pom.xml | 2 +- pom.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index 166e5fb6c9..0455eac2f2 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -125,7 +125,7 @@ com.zaxxer - HikariCP-java6 + HikariCP diff --git a/pom.xml b/pom.xml index ced2485ee6..b8e26e2258 100644 --- a/pom.xml +++ b/pom.xml @@ -534,8 +534,8 @@ com.zaxxer - HikariCP-java6 - 2.3.8 + HikariCP + 2.4.1 From 90e4cb97ffdfd8085af13109ef892da81c430938 Mon Sep 17 00:00:00 2001 From: Mark Janssen Date: Thu, 8 Oct 2015 22:26:18 +0200 Subject: [PATCH 100/465] Upgrade jetty-maven-plugin and configure war path Configuring war path enables `mvn jetty:run-war`. --- openid-connect-server-webapp/pom.xml | 1 + pom.xml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index 0455eac2f2..16fc6e6e6e 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -78,6 +78,7 @@ org.eclipse.jetty jetty-maven-plugin + ${project.build.directory}/openid-connect-server-webapp.war /openid-connect-server-webapp diff --git a/pom.xml b/pom.xml index b8e26e2258..ab7b4e971b 100644 --- a/pom.xml +++ b/pom.xml @@ -117,7 +117,7 @@ org.eclipse.jetty jetty-maven-plugin - 9.1.1.v20140108 + 9.3.3.v20150827 true From 301802abd3d8c57cb7eb7cb03bcbbc38ff889e45 Mon Sep 17 00:00:00 2001 From: Mark Janssen Date: Thu, 8 Oct 2015 22:28:32 +0200 Subject: [PATCH 101/465] Speed up servlet start - Set metadata-complete="true" attribute on the element. - Add an empty element. See: https://wiki.apache.org/tomcat/HowTo/FasterStartUp#Configure_your_web_ap plication On my (old) machine, this reduces startup time with Jetty from 137580ms to 20166ms. --- openid-connect-server-webapp/src/main/webapp/WEB-INF/web.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/web.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/web.xml index 39b6dcd6a0..3d537827c4 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/web.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/web.xml @@ -17,7 +17,10 @@ --> + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" + metadata-complete="true"> + + From 98e1d261340b2c6419a109485621e8704bd4fe21 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 12 Oct 2015 17:56:31 -0400 Subject: [PATCH 102/465] limited when login_hint is sent to the server, closes #963 --- .../service/impl/WebfingerIssuerService.java | 56 +++++++++++++------ 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/WebfingerIssuerService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/WebfingerIssuerService.java index 0573db7056..383df2e003 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/WebfingerIssuerService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/WebfingerIssuerService.java @@ -63,8 +63,18 @@ public class WebfingerIssuerService implements IssuerService { private static final Logger logger = LoggerFactory.getLogger(WebfingerIssuerService.class); // map of user input -> issuer, loaded dynamically from webfinger discover - private LoadingCache issuers; - + private LoadingCache issuers; + + // private data shuttle class to get back two bits of info from the cache loader + private class LoadingResult { + public String loginHint; + public String issuer; + public LoadingResult(String loginHint, String issuer) { + this.loginHint = loginHint; + this.issuer = issuer; + } + } + private Set whitelist = new HashSet<>(); private Set blacklist = new HashSet<>(); @@ -96,16 +106,16 @@ public IssuerServiceResponse getIssuer(HttpServletRequest request) { String identifier = request.getParameter(parameterName); if (!Strings.isNullOrEmpty(identifier)) { try { - String issuer = issuers.get(WebfingerURLNormalizer.normalizeResource(identifier)); - if (!whitelist.isEmpty() && !whitelist.contains(issuer)) { - throw new AuthenticationServiceException("Whitelist was nonempty, issuer was not in whitelist: " + issuer); + LoadingResult lr = issuers.get(identifier); + if (!whitelist.isEmpty() && !whitelist.contains(lr.issuer)) { + throw new AuthenticationServiceException("Whitelist was nonempty, issuer was not in whitelist: " + lr.issuer); } - if (blacklist.contains(issuer)) { - throw new AuthenticationServiceException("Issuer was in blacklist: " + issuer); + if (blacklist.contains(lr.issuer)) { + throw new AuthenticationServiceException("Issuer was in blacklist: " + lr.issuer); } - return new IssuerServiceResponse(issuer, identifier, null); + return new IssuerServiceResponse(lr.issuer, lr.loginHint, null); } catch (UncheckedExecutionException | ExecutionException e) { logger.warn("Issue fetching issuer for user input: " + identifier + ": " + e.getMessage()); return null; @@ -192,7 +202,7 @@ public void setForceHttps(boolean forceHttps) { * @author jricher * */ - private class WebfingerIssuerFetcher extends CacheLoader { + private class WebfingerIssuerFetcher extends CacheLoader { private HttpClient httpClient = HttpClientBuilder.create() .useSystemProperties() .build(); @@ -200,22 +210,25 @@ private class WebfingerIssuerFetcher extends CacheLoader private JsonParser parser = new JsonParser(); @Override - public String load(UriComponents key) throws Exception { + public LoadingResult load(String identifier) throws Exception { + UriComponents key = WebfingerURLNormalizer.normalizeResource(identifier); + RestTemplate restTemplate = new RestTemplate(httpFactory); // construct the URL to go to - // preserving http scheme is strictly for demo system use only. String scheme = key.getScheme(); + // preserving http scheme is strictly for demo system use only. if (!Strings.isNullOrEmpty(scheme) &&scheme.equals("http")) { if (forceHttps) { - throw new IllegalArgumentException("Scheme must start with htps"); + throw new IllegalArgumentException("Scheme must not be 'http'"); } else { logger.warn("Webfinger endpoint MUST use the https URI scheme, overriding by configuration"); scheme = "http://"; // add on colon and slashes. } } else { + // otherwise we don't know the scheme, assume HTTPS scheme = "https://"; } @@ -227,7 +240,7 @@ public String load(UriComponents key) throws Exception { + "/.well-known/webfinger" + (Strings.isNullOrEmpty(key.getQuery()) ? "" : "?" + key.getQuery()) ); - builder.addParameter("resource", key.toString()); + builder.addParameter("resource", identifier); builder.addParameter("rel", "http://openid.net/specs/connect/1.0/issuer"); try { @@ -249,7 +262,16 @@ public String load(UriComponents key) throws Exception { && linkObj.get("rel").getAsString().equals("http://openid.net/specs/connect/1.0/issuer")) { // we found the issuer, return it - return linkObj.get("href").getAsString(); + String href = linkObj.get("href").getAsString(); + + if (identifier.equals(href) + || identifier.startsWith("http")) { + // try to avoid sending a URL as the login hint + return new LoadingResult(null, href); + } else { + // otherwise pass back whatever the user typed as a login hint + return new LoadingResult(identifier, href); + } } } } @@ -262,11 +284,11 @@ public String load(UriComponents key) throws Exception { if (key.getScheme().equals("http") || key.getScheme().equals("https")) { // if it looks like HTTP then punt: return the input, hope for the best - logger.warn("Returning normalized input string as issuer, hoping for the best: " + key.toString()); - return key.toString(); + logger.warn("Returning normalized input string as issuer, hoping for the best: " + identifier); + return new LoadingResult(null, identifier); } else { // if it's not HTTP, give up - logger.warn("Couldn't find issuer: " + key.toString()); + logger.warn("Couldn't find issuer: " + identifier); throw new IllegalArgumentException(); } From d280ca40a40f6a9597237faf39fa385474888695 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 12 Oct 2015 20:04:02 -0400 Subject: [PATCH 103/465] login hints now handled in a slightly smarter (and more pluggable) manner, closes #851 --- .../connect/service/LoginHintExtracter.java | 32 ++++++++++ .../filter/AuthorizationRequestFilter.java | 23 ++++---- .../impl/MatchLoginHintsAgainstUsers.java | 59 +++++++++++++++++++ .../service/impl/PassAllLoginHints.java | 38 ++++++++++++ .../impl/RemoveLoginHintsWithHTTP.java | 48 +++++++++++++++ 5 files changed, 188 insertions(+), 12 deletions(-) create mode 100644 openid-connect-common/src/main/java/org/mitre/openid/connect/service/LoginHintExtracter.java create mode 100644 openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MatchLoginHintsAgainstUsers.java create mode 100644 openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/PassAllLoginHints.java create mode 100644 openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/RemoveLoginHintsWithHTTP.java diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/LoginHintExtracter.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/LoginHintExtracter.java new file mode 100644 index 0000000000..58955b44fd --- /dev/null +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/LoginHintExtracter.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright 2015 The MITRE Corporation + * and the MIT Kerberos and Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +package org.mitre.openid.connect.service; + +/** + * @author jricher + * + */ +public interface LoginHintExtracter { + + /** + * @param loginHint + * @return + */ + public String extractHint(String loginHint); + +} diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/AuthorizationRequestFilter.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/AuthorizationRequestFilter.java index a227642755..b538683140 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/AuthorizationRequestFilter.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/AuthorizationRequestFilter.java @@ -19,6 +19,8 @@ */ package org.mitre.openid.connect.filter; +import static org.mitre.openid.connect.request.ConnectRequestParameters.*; + import java.io.IOException; import java.net.URISyntaxException; import java.util.Date; @@ -37,6 +39,8 @@ import org.apache.http.client.utils.URIBuilder; import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.service.ClientDetailsEntityService; +import org.mitre.openid.connect.service.LoginHintExtracter; +import org.mitre.openid.connect.service.impl.RemoveLoginHintsWithHTTP; import org.mitre.openid.connect.web.AuthenticationTimeStamper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -53,16 +57,6 @@ import com.google.common.base.Splitter; import com.google.common.base.Strings; -import static org.mitre.openid.connect.request.ConnectRequestParameters.ERROR; -import static org.mitre.openid.connect.request.ConnectRequestParameters.LOGIN_HINT; -import static org.mitre.openid.connect.request.ConnectRequestParameters.LOGIN_REQUIRED; -import static org.mitre.openid.connect.request.ConnectRequestParameters.MAX_AGE; -import static org.mitre.openid.connect.request.ConnectRequestParameters.PROMPT; -import static org.mitre.openid.connect.request.ConnectRequestParameters.PROMPT_LOGIN; -import static org.mitre.openid.connect.request.ConnectRequestParameters.PROMPT_NONE; -import static org.mitre.openid.connect.request.ConnectRequestParameters.PROMPT_SEPARATOR; -import static org.mitre.openid.connect.request.ConnectRequestParameters.STATE; - /** * @author jricher * @@ -87,6 +81,9 @@ public class AuthorizationRequestFilter extends GenericFilterBean { @Autowired private RedirectResolver redirectResolver; + @Autowired(required = false) + private LoginHintExtracter loginHintExtracter = new RemoveLoginHintsWithHTTP(); + /** * */ @@ -115,8 +112,10 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) } // save the login hint to the session - if (authRequest.getExtensions().get(LOGIN_HINT) != null) { - session.setAttribute(LOGIN_HINT, authRequest.getExtensions().get(LOGIN_HINT)); + // but first check to see if the login hint makes any sense + String loginHint = loginHintExtracter.extractHint((String) authRequest.getExtensions().get(LOGIN_HINT)); + if (!Strings.isNullOrEmpty(loginHint)) { + session.setAttribute(LOGIN_HINT, loginHint); } else { session.removeAttribute(LOGIN_HINT); } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MatchLoginHintsAgainstUsers.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MatchLoginHintsAgainstUsers.java new file mode 100644 index 0000000000..95a8ae6c1d --- /dev/null +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MatchLoginHintsAgainstUsers.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright 2015 The MITRE Corporation + * and the MIT Kerberos and Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +package org.mitre.openid.connect.service.impl; + +import org.mitre.openid.connect.model.UserInfo; +import org.mitre.openid.connect.service.LoginHintExtracter; +import org.mitre.openid.connect.service.UserInfoService; +import org.springframework.beans.factory.annotation.Autowired; + +import com.google.common.base.Strings; + +/** + * Checks the login hint against the User Info collection, only populates it if a user is found. + * @author jricher + * + */ +public class MatchLoginHintsAgainstUsers implements LoginHintExtracter { + + @Autowired + private UserInfoService userInfoService; + + /* (non-Javadoc) + * @see org.mitre.openid.connect.service.LoginHintTester#useHint(java.lang.String) + */ + @Override + public String extractHint(String loginHint) { + if (Strings.isNullOrEmpty(loginHint)) { + return null; + } else { + UserInfo user = userInfoService.getByEmailAddress(loginHint); + if (user == null) { + user = userInfoService.getByUsername(loginHint); + if (user == null) { + return null; + } else { + return user.getPreferredUsername(); + } + } else { + return user.getPreferredUsername(); + } + } + } + +} diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/PassAllLoginHints.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/PassAllLoginHints.java new file mode 100644 index 0000000000..6eb7dfcb9b --- /dev/null +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/PassAllLoginHints.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright 2015 The MITRE Corporation + * and the MIT Kerberos and Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +package org.mitre.openid.connect.service.impl; + +import org.mitre.openid.connect.service.LoginHintExtracter; + +/** + * Sends all login hints through to the login page regardless of setup. + * + * @author jricher + * + */ +public class PassAllLoginHints implements LoginHintExtracter { + + /* (non-Javadoc) + * @see org.mitre.openid.connect.service.LoginHintTester#useHint(java.lang.String) + */ + @Override + public String extractHint(String loginHint) { + return loginHint; + } + +} diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/RemoveLoginHintsWithHTTP.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/RemoveLoginHintsWithHTTP.java new file mode 100644 index 0000000000..ba05b06504 --- /dev/null +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/RemoveLoginHintsWithHTTP.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright 2015 The MITRE Corporation + * and the MIT Kerberos and Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +package org.mitre.openid.connect.service.impl; + +import org.mitre.openid.connect.service.LoginHintExtracter; + +import com.google.common.base.Strings; + +/** + * Passes login hints that don't start with "http" + * + * @author jricher + * + */ +public class RemoveLoginHintsWithHTTP implements LoginHintExtracter { + + /* (non-Javadoc) + * @see org.mitre.openid.connect.service.LoginHintTester#useHint(java.lang.String) + */ + @Override + public String extractHint(String loginHint) { + if (Strings.isNullOrEmpty(loginHint)) { + return null; + } else { + if (loginHint.startsWith("http")) { + return null; + } else { + return loginHint; + } + } + } + +} From b89fa7028d89154eed9dbb51b019deaf5c319cb4 Mon Sep 17 00:00:00 2001 From: Mark Janssen Date: Mon, 12 Oct 2015 22:44:25 +0200 Subject: [PATCH 104/465] Use Maven BOM dependency for Spring The Maven "bill of materials" dependency ensures that all Spring dependencies use the same version, without having to specify them all. http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#overview-maven-bom --- pom.xml | 100 ++++++++++++++------------------------------------------ 1 file changed, 24 insertions(+), 76 deletions(-) diff --git a/pom.xml b/pom.xml index ab7b4e971b..102aa087fa 100644 --- a/pom.xml +++ b/pom.xml @@ -70,8 +70,6 @@ 1.7 - 4.1.7.RELEASE - 3.2.8.RELEASE 1.7.7 A reference implementation of OpenID Connect (http://openid.net/connect/), OAuth 2.0, and UMA built on top of Java, Spring, and Spring Security. The project contains a fully functioning server, client, and utility library. @@ -257,18 +255,16 @@ - org.springframework - spring-core - ${org.springframework-version} - - - org.springframework - spring-webmvc - ${org.springframework-version} + spring-framework-bom + 4.1.7.RELEASE + pom + import + + com.fasterxml.jackson.core jackson-databind @@ -279,73 +275,19 @@ jackson-annotations 2.3.4 - - org.springframework - spring-tx - ${org.springframework-version} - - - org.springframework - spring-orm - ${org.springframework-version} - - - - commons-logging - commons-logging - - - - + org.springframework.security - spring-security-core - ${spring.security.version} - - - org.springframework - * - - - - - org.springframework.security - spring-security-config - ${spring.security.version} - - - org.springframework - * - - - - - org.springframework.security - spring-security-taglibs - ${spring.security.version} - - - org.springframework - * - - - - - org.springframework.security - spring-security-web - ${spring.security.version} - - - org.springframework - * - - + spring-security-bom + 3.2.8.RELEASE + pom + import org.springframework.security.oauth - 2.0.3.RELEASE spring-security-oauth2 + 2.0.3.RELEASE @@ -457,12 +399,6 @@ 2.0 test - - org.springframework - spring-test - ${org.springframework-version} - test - org.mockito mockito-all @@ -525,6 +461,12 @@ org.apache.httpcomponents httpclient 4.3.6 + + + commons-logging + commons-logging + + com.nimbusds @@ -553,6 +495,12 @@ org.springframework spring-test + + + commons-logging + commons-logging + + org.mockito From d337e14de3f83fdc954954b4a24647294dc4a492 Mon Sep 17 00:00:00 2001 From: Mark Janssen Date: Mon, 12 Oct 2015 22:44:25 +0200 Subject: [PATCH 105/465] Remove transitive commons-logging dependencies We use slf4j instead; jcl-over-slf4j needs to be a compile-time dependency because we use it in several classes. Unfortunately Maven does not have a way to exclude commons-logging globally, so we need to figure out which dependencies include it through `mvn dependency:tree` and specify an `` for each of them. Finally, we upgrade to slf4j 1.7.12: http://www.slf4j.org/news.html. --- openid-connect-common/pom.xml | 6 ++++++ openid-connect-server-webapp/pom.xml | 6 ++++++ pom.xml | 7 +++++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/openid-connect-common/pom.xml b/openid-connect-common/pom.xml index 7156af5f06..1b9db7adf6 100644 --- a/openid-connect-common/pom.xml +++ b/openid-connect-common/pom.xml @@ -31,6 +31,12 @@ org.springframework spring-core + + + commons-logging + commons-logging + + org.springframework diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index 16fc6e6e6e..354ddcc295 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -94,6 +94,12 @@ org.springframework spring-orm + + + commons-logging + commons-logging + + org.slf4j diff --git a/pom.xml b/pom.xml index 102aa087fa..49c37479a3 100644 --- a/pom.xml +++ b/pom.xml @@ -70,7 +70,7 @@ 1.7 - 1.7.7 + 1.7.12 A reference implementation of OpenID Connect (http://openid.net/connect/), OAuth 2.0, and UMA built on top of Java, Spring, and Spring Security. The project contains a fully functioning server, client, and utility library. https://github.com/mitreid-connect @@ -353,7 +353,6 @@ org.slf4j jcl-over-slf4j ${org.slf4j-version} - runtime org.slf4j @@ -510,6 +509,10 @@ org.slf4j slf4j-jdk14 + + org.slf4j + jcl-over-slf4j + javax.servlet servlet-api From c67611e97573a934b249a1571a6295125d21025a Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 12 Oct 2015 21:15:30 -0400 Subject: [PATCH 106/465] added qualifier name to persistence unit and transaction manager, closes #883 --- .../src/main/webapp/WEB-INF/jpa-config.xml | 2 ++ .../impl/JpaAuthenticationHolderRepository.java | 10 +++++----- .../impl/JpaAuthorizationCodeRepository.java | 8 ++++---- .../impl/JpaOAuth2ClientRepository.java | 4 ++-- .../impl/JpaOAuth2TokenRepository.java | 14 +++++++------- .../impl/JpaSystemScopeRepository.java | 12 ++++++------ .../DefaultOAuth2AuthorizationCodeService.java | 2 +- .../repository/impl/JpaAddressRepository.java | 4 ++-- .../impl/JpaApprovedSiteRepository.java | 14 +++++++------- .../impl/JpaBlacklistedSiteRepository.java | 12 ++++++------ .../impl/JpaPairwiseIdentifierRepository.java | 4 ++-- .../repository/impl/JpaUserInfoRepository.java | 2 +- .../impl/JpaWhitelistedSiteRepository.java | 16 ++++++++-------- .../service/impl/DefaultApprovedSiteService.java | 6 +++--- .../impl/DefaultBlacklistedSiteService.java | 2 +- .../impl/DefaultWhitelistedSiteService.java | 2 +- .../repository/impl/JpaPermissionRepository.java | 8 ++++---- .../impl/JpaResourceSetRepository.java | 6 +++--- .../service/impl/JpaRegisteredClientService.java | 4 ++-- 19 files changed, 67 insertions(+), 65 deletions(-) diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/jpa-config.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/jpa-config.xml index 2ac96ba9d8..3531258115 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/jpa-config.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/jpa-config.xml @@ -31,6 +31,7 @@ + @@ -46,6 +47,7 @@ + diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthenticationHolderRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthenticationHolderRepository.java index 497ed6e231..b71b578e7b 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthenticationHolderRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthenticationHolderRepository.java @@ -29,12 +29,12 @@ import org.springframework.transaction.annotation.Transactional; @Repository -@Transactional +@Transactional(value="defaultTransactionManager") public class JpaAuthenticationHolderRepository implements AuthenticationHolderRepository { private static final int MAXEXPIREDRESULTS = 1000; - @PersistenceContext + @PersistenceContext(unitName="defaultPersistenceUnit") private EntityManager manager; @Override @@ -49,7 +49,7 @@ public AuthenticationHolderEntity getById(Long id) { } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public void remove(AuthenticationHolderEntity a) { AuthenticationHolderEntity found = getById(a.getId()); if (found != null) { @@ -60,13 +60,13 @@ public void remove(AuthenticationHolderEntity a) { } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public AuthenticationHolderEntity save(AuthenticationHolderEntity a) { return JpaUtil.saveOrUpdate(a.getId(), manager, a); } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public List getOrphanedAuthenticationHolders() { TypedQuery query = manager.createNamedQuery(AuthenticationHolderEntity.QUERY_GET_UNUSED, AuthenticationHolderEntity.class); query.setMaxResults(MAXEXPIREDRESULTS); diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthorizationCodeRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthorizationCodeRepository.java index 58b6adcca3..ac325e589f 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthorizationCodeRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthorizationCodeRepository.java @@ -39,17 +39,17 @@ * */ @Repository -@Transactional +@Transactional(value="defaultTransactionManager") public class JpaAuthorizationCodeRepository implements AuthorizationCodeRepository { - @PersistenceContext + @PersistenceContext(unitName="defaultPersistenceUnit") EntityManager manager; /* (non-Javadoc) * @see org.mitre.oauth2.repository.AuthorizationCodeRepository#save(org.mitre.oauth2.model.AuthorizationCodeEntity) */ @Override - @Transactional + @Transactional(value="defaultTransactionManager") public AuthorizationCodeEntity save(AuthorizationCodeEntity authorizationCode) { return JpaUtil.saveOrUpdate(authorizationCode.getId(), manager, authorizationCode); @@ -60,7 +60,7 @@ public AuthorizationCodeEntity save(AuthorizationCodeEntity authorizationCode) { * @see org.mitre.oauth2.repository.AuthorizationCodeRepository#getByCode(java.lang.String) */ @Override - @Transactional + @Transactional(value="defaultTransactionManager") public AuthorizationCodeEntity getByCode(String code) { TypedQuery query = manager.createNamedQuery(AuthorizationCodeEntity.QUERY_BY_VALUE, AuthorizationCodeEntity.class); query.setParameter("code", code); diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2ClientRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2ClientRepository.java index ff80d43c42..0cbc4d4c74 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2ClientRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2ClientRepository.java @@ -33,10 +33,10 @@ * */ @Repository -@Transactional +@Transactional(value="defaultTransactionManager") public class JpaOAuth2ClientRepository implements OAuth2ClientRepository { - @PersistenceContext + @PersistenceContext(unitName="defaultPersistenceUnit") private EntityManager manager; public JpaOAuth2ClientRepository() { diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java index 0e865fe09f..ad63dafab4 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java @@ -43,7 +43,7 @@ public class JpaOAuth2TokenRepository implements OAuth2TokenRepository { private static final int MAXEXPIREDRESULTS = 1000; - @PersistenceContext + @PersistenceContext(unitName="defaultPersistenceUnit") private EntityManager manager; @Override @@ -77,13 +77,13 @@ public OAuth2AccessTokenEntity getAccessTokenById(Long id) { } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public OAuth2AccessTokenEntity saveAccessToken(OAuth2AccessTokenEntity token) { return JpaUtil.saveOrUpdate(token.getId(), manager, token); } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public void removeAccessToken(OAuth2AccessTokenEntity accessToken) { OAuth2AccessTokenEntity found = getAccessTokenByValue(accessToken.getValue()); if (found != null) { @@ -94,7 +94,7 @@ public void removeAccessToken(OAuth2AccessTokenEntity accessToken) { } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public void clearAccessTokensForRefreshToken(OAuth2RefreshTokenEntity refreshToken) { TypedQuery query = manager.createNamedQuery(OAuth2AccessTokenEntity.QUERY_BY_REFRESH_TOKEN, OAuth2AccessTokenEntity.class); query.setParameter(OAuth2AccessTokenEntity.PARAM_REFERSH_TOKEN, refreshToken); @@ -122,13 +122,13 @@ public OAuth2RefreshTokenEntity getRefreshTokenById(Long id) { } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public OAuth2RefreshTokenEntity saveRefreshToken(OAuth2RefreshTokenEntity refreshToken) { return JpaUtil.saveOrUpdate(refreshToken.getId(), manager, refreshToken); } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public void removeRefreshToken(OAuth2RefreshTokenEntity refreshToken) { OAuth2RefreshTokenEntity found = getRefreshTokenByValue(refreshToken.getValue()); if (found != null) { @@ -139,7 +139,7 @@ public void removeRefreshToken(OAuth2RefreshTokenEntity refreshToken) { } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public void clearTokensForClient(ClientDetailsEntity client) { TypedQuery queryA = manager.createNamedQuery(OAuth2AccessTokenEntity.QUERY_BY_CLIENT, OAuth2AccessTokenEntity.class); queryA.setParameter(OAuth2AccessTokenEntity.PARAM_CLIENT, client); diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaSystemScopeRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaSystemScopeRepository.java index 53027e8c11..20cfa63abf 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaSystemScopeRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaSystemScopeRepository.java @@ -41,14 +41,14 @@ @Repository("jpaSystemScopeRepository") public class JpaSystemScopeRepository implements SystemScopeRepository { - @PersistenceContext + @PersistenceContext(unitName="defaultPersistenceUnit") private EntityManager em; /* (non-Javadoc) * @see org.mitre.oauth2.repository.SystemScopeRepository#getAll() */ @Override - @Transactional + @Transactional(value="defaultTransactionManager") public Set getAll() { TypedQuery query = em.createNamedQuery(SystemScope.QUERY_ALL, SystemScope.class); @@ -59,7 +59,7 @@ public Set getAll() { * @see org.mitre.oauth2.repository.SystemScopeRepository#getById(java.lang.Long) */ @Override - @Transactional + @Transactional(value="defaultTransactionManager") public SystemScope getById(Long id) { return em.find(SystemScope.class, id); } @@ -68,7 +68,7 @@ public SystemScope getById(Long id) { * @see org.mitre.oauth2.repository.SystemScopeRepository#getByValue(java.lang.String) */ @Override - @Transactional + @Transactional(value="defaultTransactionManager") public SystemScope getByValue(String value) { TypedQuery query = em.createNamedQuery(SystemScope.QUERY_BY_VALUE, SystemScope.class); query.setParameter(SystemScope.PARAM_VALUE, value); @@ -79,7 +79,7 @@ public SystemScope getByValue(String value) { * @see org.mitre.oauth2.repository.SystemScopeRepository#remove(org.mitre.oauth2.model.SystemScope) */ @Override - @Transactional + @Transactional(value="defaultTransactionManager") public void remove(SystemScope scope) { SystemScope found = getById(scope.getId()); @@ -93,7 +93,7 @@ public void remove(SystemScope scope) { * @see org.mitre.oauth2.repository.SystemScopeRepository#save(org.mitre.oauth2.model.SystemScope) */ @Override - @Transactional + @Transactional(value="defaultTransactionManager") public SystemScope save(SystemScope scope) { return saveOrUpdate(scope.getId(), em, scope); } diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2AuthorizationCodeService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2AuthorizationCodeService.java index 36cb51644f..8403a6f5b5 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2AuthorizationCodeService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2AuthorizationCodeService.java @@ -112,7 +112,7 @@ public OAuth2Authentication consumeAuthorizationCode(String code) throws Invalid /** * Find and remove all expired auth codes. */ - @Transactional + @Transactional(value="defaultTransactionManager") public void clearExpiredAuthorizationCodes() { Collection codes = repository.getExpiredCodes(); diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaAddressRepository.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaAddressRepository.java index ff7fbb97ed..8634c1b813 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaAddressRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaAddressRepository.java @@ -33,11 +33,11 @@ @Repository public class JpaAddressRepository implements AddressRepository { - @PersistenceContext + @PersistenceContext(unitName="defaultPersistenceUnit") private EntityManager manager; @Override - @Transactional + @Transactional(value="defaultTransactionManager") public Address getById(Long id) { return manager.find(Address.class, id); } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaApprovedSiteRepository.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaApprovedSiteRepository.java index 330116e230..d0869521d2 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaApprovedSiteRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaApprovedSiteRepository.java @@ -38,24 +38,24 @@ @Repository public class JpaApprovedSiteRepository implements ApprovedSiteRepository { - @PersistenceContext + @PersistenceContext(unitName="defaultPersistenceUnit") private EntityManager manager; @Override - @Transactional + @Transactional(value="defaultTransactionManager") public Collection getAll() { TypedQuery query = manager.createNamedQuery(ApprovedSite.QUERY_ALL, ApprovedSite.class); return query.getResultList(); } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public ApprovedSite getById(Long id) { return manager.find(ApprovedSite.class, id); } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public void remove(ApprovedSite approvedSite) { ApprovedSite found = manager.find(ApprovedSite.class, approvedSite.getId()); @@ -67,7 +67,7 @@ public void remove(ApprovedSite approvedSite) { } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public ApprovedSite save(ApprovedSite approvedSite) { return saveOrUpdate(approvedSite.getId(), manager, approvedSite); } @@ -83,7 +83,7 @@ public Collection getByClientIdAndUserId(String clientId, String u } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public Collection getByUserId(String userId) { TypedQuery query = manager.createNamedQuery(ApprovedSite.QUERY_BY_USER_ID, ApprovedSite.class); query.setParameter(ApprovedSite.PARAM_USER_ID, userId); @@ -93,7 +93,7 @@ public Collection getByUserId(String userId) { } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public Collection getByClientId(String clientId) { TypedQuery query = manager.createNamedQuery(ApprovedSite.QUERY_BY_CLIENT_ID, ApprovedSite.class); query.setParameter(ApprovedSite.PARAM_CLIENT_ID, clientId); diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaBlacklistedSiteRepository.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaBlacklistedSiteRepository.java index 762a578241..53b7fad1ee 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaBlacklistedSiteRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaBlacklistedSiteRepository.java @@ -39,14 +39,14 @@ @Repository public class JpaBlacklistedSiteRepository implements BlacklistedSiteRepository { - @PersistenceContext + @PersistenceContext(unitName="defaultPersistenceUnit") private EntityManager manager; /* (non-Javadoc) * @see org.mitre.openid.connect.repository.BlacklistedSiteRepository#getAll() */ @Override - @Transactional + @Transactional(value="defaultTransactionManager") public Collection getAll() { TypedQuery query = manager.createNamedQuery(BlacklistedSite.QUERY_ALL, BlacklistedSite.class); return query.getResultList(); @@ -56,7 +56,7 @@ public Collection getAll() { * @see org.mitre.openid.connect.repository.BlacklistedSiteRepository#getById(java.lang.Long) */ @Override - @Transactional + @Transactional(value="defaultTransactionManager") public BlacklistedSite getById(Long id) { return manager.find(BlacklistedSite.class, id); } @@ -65,7 +65,7 @@ public BlacklistedSite getById(Long id) { * @see org.mitre.openid.connect.repository.BlacklistedSiteRepository#remove(org.mitre.openid.connect.model.BlacklistedSite) */ @Override - @Transactional + @Transactional(value="defaultTransactionManager") public void remove(BlacklistedSite blacklistedSite) { BlacklistedSite found = manager.find(BlacklistedSite.class, blacklistedSite.getId()); @@ -81,7 +81,7 @@ public void remove(BlacklistedSite blacklistedSite) { * @see org.mitre.openid.connect.repository.BlacklistedSiteRepository#save(org.mitre.openid.connect.model.BlacklistedSite) */ @Override - @Transactional + @Transactional(value="defaultTransactionManager") public BlacklistedSite save(BlacklistedSite blacklistedSite) { return saveOrUpdate(blacklistedSite.getId(), manager, blacklistedSite); } @@ -90,7 +90,7 @@ public BlacklistedSite save(BlacklistedSite blacklistedSite) { * @see org.mitre.openid.connect.repository.BlacklistedSiteRepository#update(org.mitre.openid.connect.model.BlacklistedSite, org.mitre.openid.connect.model.BlacklistedSite) */ @Override - @Transactional + @Transactional(value="defaultTransactionManager") public BlacklistedSite update(BlacklistedSite oldBlacklistedSite, BlacklistedSite blacklistedSite) { blacklistedSite.setId(oldBlacklistedSite.getId()); diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaPairwiseIdentifierRepository.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaPairwiseIdentifierRepository.java index 658517e75a..2a37a910db 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaPairwiseIdentifierRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaPairwiseIdentifierRepository.java @@ -38,7 +38,7 @@ @Repository public class JpaPairwiseIdentifierRepository implements PairwiseIdentifierRepository { - @PersistenceContext + @PersistenceContext(unitName="defaultPersistenceUnit") private EntityManager manager; /* (non-Javadoc) @@ -57,7 +57,7 @@ public PairwiseIdentifier getBySectorIdentifier(String sub, String sectorIdentif * @see org.mitre.openid.connect.repository.PairwiseIdentifierRepository#save(org.mitre.openid.connect.model.PairwiseIdentifier) */ @Override - @Transactional + @Transactional(value="defaultTransactionManager") public void save(PairwiseIdentifier pairwise) { saveOrUpdate(pairwise.getId(), manager, pairwise); } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaUserInfoRepository.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaUserInfoRepository.java index 936eecd363..fec468cc6d 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaUserInfoRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaUserInfoRepository.java @@ -36,7 +36,7 @@ @Repository("jpaUserInfoRepository") public class JpaUserInfoRepository implements UserInfoRepository { - @PersistenceContext + @PersistenceContext(unitName="defaultPersistenceUnit") private EntityManager manager; /** diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaWhitelistedSiteRepository.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaWhitelistedSiteRepository.java index c26c03917c..0f157befe6 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaWhitelistedSiteRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaWhitelistedSiteRepository.java @@ -39,24 +39,24 @@ @Repository public class JpaWhitelistedSiteRepository implements WhitelistedSiteRepository { - @PersistenceContext + @PersistenceContext(unitName="defaultPersistenceUnit") private EntityManager manager; @Override - @Transactional + @Transactional(value="defaultTransactionManager") public Collection getAll() { TypedQuery query = manager.createNamedQuery(WhitelistedSite.QUERY_ALL, WhitelistedSite.class); return query.getResultList(); } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public WhitelistedSite getById(Long id) { return manager.find(WhitelistedSite.class, id); } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public void remove(WhitelistedSite whitelistedSite) { WhitelistedSite found = manager.find(WhitelistedSite.class, whitelistedSite.getId()); @@ -68,13 +68,13 @@ public void remove(WhitelistedSite whitelistedSite) { } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public WhitelistedSite save(WhitelistedSite whiteListedSite) { return saveOrUpdate(whiteListedSite.getId(), manager, whiteListedSite); } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public WhitelistedSite update(WhitelistedSite oldWhitelistedSite, WhitelistedSite whitelistedSite) { // sanity check whitelistedSite.setId(oldWhitelistedSite.getId()); @@ -83,7 +83,7 @@ public WhitelistedSite update(WhitelistedSite oldWhitelistedSite, WhitelistedSit } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public WhitelistedSite getByClientId(String clientId) { TypedQuery query = manager.createNamedQuery(WhitelistedSite.QUERY_BY_CLIENT_ID, WhitelistedSite.class); query.setParameter(WhitelistedSite.PARAM_CLIENT_ID, clientId); @@ -91,7 +91,7 @@ public WhitelistedSite getByClientId(String clientId) { } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public Collection getByCreator(String creatorId) { TypedQuery query = manager.createNamedQuery(WhitelistedSite.QUERY_BY_CREATOR, WhitelistedSite.class); query.setParameter(WhitelistedSite.PARAM_USER_ID, creatorId); diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultApprovedSiteService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultApprovedSiteService.java index f7d0623b92..15145c05fa 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultApprovedSiteService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultApprovedSiteService.java @@ -65,7 +65,7 @@ public Collection getAll() { } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public ApprovedSite save(ApprovedSite approvedSite) { ApprovedSite a = approvedSiteRepository.save(approvedSite); statsService.resetCache(); @@ -78,7 +78,7 @@ public ApprovedSite getById(Long id) { } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public void remove(ApprovedSite approvedSite) { //Remove any associated access and refresh tokens @@ -97,7 +97,7 @@ public void remove(ApprovedSite approvedSite) { } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public ApprovedSite createApprovedSite(String clientId, String userId, Date timeoutDate, Set allowedScopes) { ApprovedSite as = approvedSiteRepository.save(new ApprovedSite()); diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultBlacklistedSiteService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultBlacklistedSiteService.java index f88bfd7de5..16c7bf4f3f 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultBlacklistedSiteService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultBlacklistedSiteService.java @@ -35,7 +35,7 @@ * */ @Service -@Transactional +@Transactional(value="defaultTransactionManager") public class DefaultBlacklistedSiteService implements BlacklistedSiteService { @Autowired diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultWhitelistedSiteService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultWhitelistedSiteService.java index 86c141c8fd..d5db58b91e 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultWhitelistedSiteService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultWhitelistedSiteService.java @@ -32,7 +32,7 @@ * */ @Service -@Transactional +@Transactional(value="defaultTransactionManager") public class DefaultWhitelistedSiteService implements WhitelistedSiteService { @Autowired diff --git a/uma-server/src/main/java/org/mitre/uma/repository/impl/JpaPermissionRepository.java b/uma-server/src/main/java/org/mitre/uma/repository/impl/JpaPermissionRepository.java index 213cd7d67a..f0adffa4dd 100644 --- a/uma-server/src/main/java/org/mitre/uma/repository/impl/JpaPermissionRepository.java +++ b/uma-server/src/main/java/org/mitre/uma/repository/impl/JpaPermissionRepository.java @@ -38,11 +38,11 @@ @Repository public class JpaPermissionRepository implements PermissionRepository { - @PersistenceContext + @PersistenceContext(unitName="defaultPersistenceUnit") private EntityManager em; @Override - @Transactional + @Transactional(value="defaultTransactionManager") public PermissionTicket save(PermissionTicket p) { return JpaUtil.saveOrUpdate(p.getId(), em, p); } @@ -70,7 +70,7 @@ public Collection getAll() { * @see org.mitre.uma.repository.PermissionRepository#saveRawPermission(org.mitre.uma.model.Permission) */ @Override - @Transactional + @Transactional(value="defaultTransactionManager") public Permission saveRawPermission(Permission p) { return JpaUtil.saveOrUpdate(p.getId(), em, p); } @@ -97,7 +97,7 @@ public Collection getPermissionTicketsForResourceSet(ResourceS * @see org.mitre.uma.repository.PermissionRepository#remove(org.mitre.uma.model.PermissionTicket) */ @Override - @Transactional + @Transactional(value="defaultTransactionManager") public void remove(PermissionTicket ticket) { PermissionTicket found = getByTicket(ticket.getTicket()); if (found != null) { diff --git a/uma-server/src/main/java/org/mitre/uma/repository/impl/JpaResourceSetRepository.java b/uma-server/src/main/java/org/mitre/uma/repository/impl/JpaResourceSetRepository.java index 2bb6d71929..ffc2bf36d0 100644 --- a/uma-server/src/main/java/org/mitre/uma/repository/impl/JpaResourceSetRepository.java +++ b/uma-server/src/main/java/org/mitre/uma/repository/impl/JpaResourceSetRepository.java @@ -38,12 +38,12 @@ @Repository public class JpaResourceSetRepository implements ResourceSetRepository { - @PersistenceContext + @PersistenceContext(unitName="defaultPersistenceUnit") private EntityManager em; private static Logger logger = LoggerFactory.getLogger(JpaResourceSetRepository.class); @Override - @Transactional + @Transactional(value="defaultTransactionManager") public ResourceSet save(ResourceSet rs) { return JpaUtil.saveOrUpdate(rs.getId(), em, rs); } @@ -54,7 +54,7 @@ public ResourceSet getById(Long id) { } @Override - @Transactional + @Transactional(value="defaultTransactionManager") public void remove(ResourceSet rs) { ResourceSet found = getById(rs.getId()); if (found != null) { diff --git a/uma-server/src/main/java/org/mitre/uma/service/impl/JpaRegisteredClientService.java b/uma-server/src/main/java/org/mitre/uma/service/impl/JpaRegisteredClientService.java index 031fbe8b87..458a97c455 100644 --- a/uma-server/src/main/java/org/mitre/uma/service/impl/JpaRegisteredClientService.java +++ b/uma-server/src/main/java/org/mitre/uma/service/impl/JpaRegisteredClientService.java @@ -37,7 +37,7 @@ @Service public class JpaRegisteredClientService implements RegisteredClientService { - @PersistenceContext + @PersistenceContext(unitName="defaultPersistenceUnit") private EntityManager em; /* (non-Javadoc) @@ -58,7 +58,7 @@ public RegisteredClient getByIssuer(String issuer) { * @see org.mitre.openid.connect.client.service.RegisteredClientService#save(java.lang.String, org.mitre.oauth2.model.RegisteredClient) */ @Override - @Transactional + @Transactional(value="defaultTransactionManager") public void save(String issuer, RegisteredClient client) { From ebb4f2c3d4da1e310ff55e03cef7049ccf6b25f1 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 13 Oct 2015 04:40:01 -0400 Subject: [PATCH 107/465] Upgraded to nimbus 4.2, closes #934 --- .../client/NamedAdminAuthoritiesMapper.java | 4 +- .../client/OIDCAuthenticationFilter.java | 29 ++++--- .../impl/EncryptedAuthRequestUrlBuilder.java | 20 ++--- .../impl/SignedAuthRequestUrlBuilder.java | 20 ++--- .../impl/TestSignedAuthRequestUrlBuilder.java | 6 +- ...aultJWTEncryptionAndDecryptionService.java | 4 +- ...DefaultJWTSigningAndValidationService.java | 80 ++++++++++--------- ...aultJWTEncryptionAndDecryptionService.java | 13 +-- .../DefaultOAuth2ProviderTokenService.java | 8 +- .../token/JWTAssertionTokenGranter.java | 10 +-- .../JWTBearerAuthenticationProvider.java | 4 +- .../request/ConnectOAuth2RequestFactory.java | 31 ++++--- .../service/impl/DefaultOIDCTokenService.java | 44 +++++----- .../connect/token/ConnectTokenEnhancer.java | 18 ++--- .../openid/connect/view/UserInfoJWTView.java | 15 ++-- pom.xml | 2 +- 16 files changed, 153 insertions(+), 155 deletions(-) diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/NamedAdminAuthoritiesMapper.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/NamedAdminAuthoritiesMapper.java index 8b941154b5..82970e42f4 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/NamedAdminAuthoritiesMapper.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/NamedAdminAuthoritiesMapper.java @@ -31,7 +31,7 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; import com.nimbusds.jwt.JWT; -import com.nimbusds.jwt.ReadOnlyJWTClaimsSet; +import com.nimbusds.jwt.JWTClaimsSet; /** * @@ -56,7 +56,7 @@ public Collection mapAuthorities(JWT idToken, UserIn Set out = new HashSet<>(); try { - ReadOnlyJWTClaimsSet claims = idToken.getJWTClaimsSet(); + JWTClaimsSet claims = idToken.getJWTClaimsSet(); SubjectIssuerGrantedAuthority authority = new SubjectIssuerGrantedAuthority(claims.getSubject(), claims.getIssuer()); out.add(authority); diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java index bf1f5215c5..9af8f5edf8 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java @@ -16,6 +16,10 @@ *******************************************************************************/ package org.mitre.openid.connect.client; +import static org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod.PRIVATE_KEY; +import static org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod.SECRET_BASIC; +import static org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod.SECRET_JWT; + import java.io.IOException; import java.math.BigInteger; import java.net.URI; @@ -75,13 +79,8 @@ import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.JWTParser; import com.nimbusds.jwt.PlainJWT; -import com.nimbusds.jwt.ReadOnlyJWTClaimsSet; import com.nimbusds.jwt.SignedJWT; -import static org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod.PRIVATE_KEY; -import static org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod.SECRET_BASIC; -import static org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod.SECRET_JWT; - /** * OpenID Connect Authentication Filter class * @@ -374,25 +373,25 @@ protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOE throw new AuthenticationServiceException("Couldn't find required signer service for use with private key auth."); } - JWTClaimsSet claimsSet = new JWTClaimsSet(); + JWTClaimsSet.Builder claimsSet = new JWTClaimsSet.Builder(); - claimsSet.setIssuer(clientConfig.getClientId()); - claimsSet.setSubject(clientConfig.getClientId()); - claimsSet.setAudience(Lists.newArrayList(serverConfig.getTokenEndpointUri())); - claimsSet.setJWTID(UUID.randomUUID().toString()); + claimsSet.issuer(clientConfig.getClientId()); + claimsSet.subject(clientConfig.getClientId()); + claimsSet.audience(Lists.newArrayList(serverConfig.getTokenEndpointUri())); + claimsSet.jwtID(UUID.randomUUID().toString()); // TODO: make this configurable Date exp = new Date(System.currentTimeMillis() + (60 * 1000)); // auth good for 60 seconds - claimsSet.setExpirationTime(exp); + claimsSet.expirationTime(exp); Date now = new Date(System.currentTimeMillis()); - claimsSet.setIssueTime(now); - claimsSet.setNotBeforeTime(now); + claimsSet.issueTime(now); + claimsSet.notBeforeTime(now); JWSHeader header = new JWSHeader(alg, null, null, null, null, null, null, null, null, null, signer.getDefaultSignerKeyId(), null, null); - SignedJWT jwt = new SignedJWT(header, claimsSet); + SignedJWT jwt = new SignedJWT(header, claimsSet.build()); signer.signJwt(jwt, alg); @@ -472,7 +471,7 @@ protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOE JWT idToken = JWTParser.parse(idTokenValue); // validate our ID Token over a number of tests - ReadOnlyJWTClaimsSet idClaims = idToken.getJWTClaimsSet(); + JWTClaimsSet idClaims = idToken.getJWTClaimsSet(); // check the signature JWTSigningAndValidationService jwtValidator = null; diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/EncryptedAuthRequestUrlBuilder.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/EncryptedAuthRequestUrlBuilder.java index 4fb3e7f6a1..07fdf42587 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/EncryptedAuthRequestUrlBuilder.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/EncryptedAuthRequestUrlBuilder.java @@ -58,33 +58,33 @@ public class EncryptedAuthRequestUrlBuilder implements AuthRequestUrlBuilder { public String buildAuthRequestUrl(ServerConfiguration serverConfig, RegisteredClient clientConfig, String redirectUri, String nonce, String state, Map options, String loginHint) { // create our signed JWT for the request object - JWTClaimsSet claims = new JWTClaimsSet(); + JWTClaimsSet.Builder claims = new JWTClaimsSet.Builder(); //set parameters to JwtClaims - claims.setClaim("response_type", "code"); - claims.setClaim("client_id", clientConfig.getClientId()); - claims.setClaim("scope", Joiner.on(" ").join(clientConfig.getScope())); + claims.claim("response_type", "code"); + claims.claim("client_id", clientConfig.getClientId()); + claims.claim("scope", Joiner.on(" ").join(clientConfig.getScope())); // build our redirect URI - claims.setClaim("redirect_uri", redirectUri); + claims.claim("redirect_uri", redirectUri); // this comes back in the id token - claims.setClaim("nonce", nonce); + claims.claim("nonce", nonce); // this comes back in the auth request return - claims.setClaim("state", state); + claims.claim("state", state); // Optional parameters for (Entry option : options.entrySet()) { - claims.setClaim(option.getKey(), option.getValue()); + claims.claim(option.getKey(), option.getValue()); } // if there's a login hint, send it if (!Strings.isNullOrEmpty(loginHint)) { - claims.setClaim("login_hint", loginHint); + claims.claim("login_hint", loginHint); } - EncryptedJWT jwt = new EncryptedJWT(new JWEHeader(alg, enc), claims); + EncryptedJWT jwt = new EncryptedJWT(new JWEHeader(alg, enc), claims.build()); JWTEncryptionAndDecryptionService encryptor = encrypterService.getEncrypter(serverConfig.getJwksUri()); diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/SignedAuthRequestUrlBuilder.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/SignedAuthRequestUrlBuilder.java index 57e645cc4c..20d13ca48e 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/SignedAuthRequestUrlBuilder.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/SignedAuthRequestUrlBuilder.java @@ -52,30 +52,30 @@ public class SignedAuthRequestUrlBuilder implements AuthRequestUrlBuilder { public String buildAuthRequestUrl(ServerConfiguration serverConfig, RegisteredClient clientConfig, String redirectUri, String nonce, String state, Map options, String loginHint) { // create our signed JWT for the request object - JWTClaimsSet claims = new JWTClaimsSet(); + JWTClaimsSet.Builder claims = new JWTClaimsSet.Builder(); //set parameters to JwtClaims - claims.setClaim("response_type", "code"); - claims.setClaim("client_id", clientConfig.getClientId()); - claims.setClaim("scope", Joiner.on(" ").join(clientConfig.getScope())); + claims.claim("response_type", "code"); + claims.claim("client_id", clientConfig.getClientId()); + claims.claim("scope", Joiner.on(" ").join(clientConfig.getScope())); // build our redirect URI - claims.setClaim("redirect_uri", redirectUri); + claims.claim("redirect_uri", redirectUri); // this comes back in the id token - claims.setClaim("nonce", nonce); + claims.claim("nonce", nonce); // this comes back in the auth request return - claims.setClaim("state", state); + claims.claim("state", state); // Optional parameters for (Entry option : options.entrySet()) { - claims.setClaim(option.getKey(), option.getValue()); + claims.claim(option.getKey(), option.getValue()); } // if there's a login hint, send it if (!Strings.isNullOrEmpty(loginHint)) { - claims.setClaim("login_hint", loginHint); + claims.claim("login_hint", loginHint); } JWSAlgorithm alg = clientConfig.getRequestObjectSigningAlg(); @@ -83,7 +83,7 @@ public String buildAuthRequestUrl(ServerConfiguration serverConfig, RegisteredCl alg = signingAndValidationService.getDefaultSigningAlgorithm(); } - SignedJWT jwt = new SignedJWT(new JWSHeader(alg), claims); + SignedJWT jwt = new SignedJWT(new JWSHeader(alg), claims.build()); signingAndValidationService.signJwt(jwt, alg); diff --git a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestSignedAuthRequestUrlBuilder.java b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestSignedAuthRequestUrlBuilder.java index b9b5767820..8f2663e380 100644 --- a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestSignedAuthRequestUrlBuilder.java +++ b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestSignedAuthRequestUrlBuilder.java @@ -43,7 +43,7 @@ import com.nimbusds.jose.jwk.KeyUse; import com.nimbusds.jose.jwk.RSAKey; import com.nimbusds.jose.util.Base64URL; -import com.nimbusds.jwt.ReadOnlyJWTClaimsSet; +import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; import static org.junit.Assert.assertEquals; @@ -130,7 +130,7 @@ public void buildAuthRequestUrl() { UriComponents components = builder.build(); String jwtString = components.getQueryParams().get("request").get(0); - ReadOnlyJWTClaimsSet claims = null; + JWTClaimsSet claims = null; try { SignedJWT jwt = SignedJWT.parse(jwtString); @@ -169,7 +169,7 @@ public void buildAuthRequestUrl_withLoginHint() { UriComponents components = builder.build(); String jwtString = components.getQueryParams().get("request").get(0); - ReadOnlyJWTClaimsSet claims = null; + JWTClaimsSet claims = null; try { SignedJWT jwt = SignedJWT.parse(jwtString); diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/encryption/service/impl/DefaultJWTEncryptionAndDecryptionService.java b/openid-connect-common/src/main/java/org/mitre/jwt/encryption/service/impl/DefaultJWTEncryptionAndDecryptionService.java index d498d99c28..e2d7ca0232 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/encryption/service/impl/DefaultJWTEncryptionAndDecryptionService.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/encryption/service/impl/DefaultJWTEncryptionAndDecryptionService.java @@ -272,11 +272,11 @@ public Collection getAllEncryptionAlgsSupported() { Set algs = new HashSet<>(); for (JWEEncrypter encrypter : encrypters.values()) { - algs.addAll(encrypter.supportedAlgorithms()); + algs.addAll(encrypter.supportedJWEAlgorithms()); } for (JWEDecrypter decrypter : decrypters.values()) { - algs.addAll(decrypter.supportedAlgorithms()); + algs.addAll(decrypter.supportedJWEAlgorithms()); } return algs; diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DefaultJWTSigningAndValidationService.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DefaultJWTSigningAndValidationService.java index 6692fb15c6..54e89f43f5 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DefaultJWTSigningAndValidationService.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DefaultJWTSigningAndValidationService.java @@ -17,6 +17,8 @@ package org.mitre.jwt.signer.service.impl; import java.security.NoSuchAlgorithmException; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; import java.security.spec.InvalidKeySpecException; import java.util.Collection; import java.util.HashMap; @@ -160,41 +162,45 @@ private void buildSignersAndVerifiers() throws NoSuchAlgorithmException, Invalid String id = jwkEntry.getKey(); JWK jwk = jwkEntry.getValue(); - if (jwk instanceof RSAKey) { - // build RSA signers & verifiers - - if (jwk.isPrivate()) { // only add the signer if there's a private key - RSASSASigner signer = new RSASSASigner(((RSAKey) jwk).toRSAPrivateKey()); - signers.put(id, signer); - } - - RSASSAVerifier verifier = new RSASSAVerifier(((RSAKey) jwk).toRSAPublicKey()); - verifiers.put(id, verifier); - - } else if (jwk instanceof ECKey) { - // build EC signers & verifiers - - if (jwk.isPrivate()) { - ECDSASigner signer = new ECDSASigner(((ECKey) jwk).getD().decodeToBigInteger()); - signers.put(id, signer); - } - - ECDSAVerifier verifier = new ECDSAVerifier(((ECKey) jwk).getX().decodeToBigInteger(), ((ECKey) jwk).getY().decodeToBigInteger()); - verifiers.put(id, verifier); - - } else if (jwk instanceof OctetSequenceKey) { - // build HMAC signers & verifiers - - if (jwk.isPrivate()) { // technically redundant check because all HMAC keys are private - MACSigner signer = new MACSigner(((OctetSequenceKey) jwk).toByteArray()); - signers.put(id, signer); + try { + if (jwk instanceof RSAKey) { + // build RSA signers & verifiers + + if (jwk.isPrivate()) { // only add the signer if there's a private key + RSASSASigner signer = new RSASSASigner((RSAKey) jwk); + signers.put(id, signer); + } + + RSASSAVerifier verifier = new RSASSAVerifier((RSAKey) jwk); + verifiers.put(id, verifier); + + } else if (jwk instanceof ECKey) { + // build EC signers & verifiers + + if (jwk.isPrivate()) { + ECDSASigner signer = new ECDSASigner((ECKey) jwk); + signers.put(id, signer); + } + + ECDSAVerifier verifier = new ECDSAVerifier((ECKey) jwk); + verifiers.put(id, verifier); + + } else if (jwk instanceof OctetSequenceKey) { + // build HMAC signers & verifiers + + if (jwk.isPrivate()) { // technically redundant check because all HMAC keys are private + MACSigner signer = new MACSigner((OctetSequenceKey) jwk); + signers.put(id, signer); + } + + MACVerifier verifier = new MACVerifier((OctetSequenceKey) jwk); + verifiers.put(id, verifier); + + } else { + logger.warn("Unknown key type: " + jwk); } - - MACVerifier verifier = new MACVerifier(((OctetSequenceKey) jwk).toByteArray()); - verifiers.put(id, verifier); - - } else { - logger.warn("Unknown key type: " + jwk); + } catch (JOSEException e) { + logger.warn("Exception loading signer/verifier", e); } } @@ -230,7 +236,7 @@ public void signJwt(SignedJWT jwt, JWSAlgorithm alg) { JWSSigner signer = null; for (JWSSigner s : signers.values()) { - if (s.supportedAlgorithms().contains(alg)) { + if (s.supportedJWSAlgorithms().contains(alg)) { signer = s; break; } @@ -292,11 +298,11 @@ public Collection getAllSigningAlgsSupported() { Set algs = new HashSet<>(); for (JWSSigner signer : signers.values()) { - algs.addAll(signer.supportedAlgorithms()); + algs.addAll(signer.supportedJWSAlgorithms()); } for (JWSVerifier verifier : verifiers.values()) { - algs.addAll(verifier.supportedAlgorithms()); + algs.addAll(verifier.supportedJWSAlgorithms()); } return algs; diff --git a/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java b/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java index c85e17f72f..69c0799137 100644 --- a/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java +++ b/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java @@ -42,7 +42,6 @@ import com.nimbusds.jose.util.JSONObjectUtils; import com.nimbusds.jwt.EncryptedJWT; import com.nimbusds.jwt.JWTClaimsSet; -import com.nimbusds.jwt.ReadOnlyJWTClaimsSet; import static org.hamcrest.CoreMatchers.nullValue; @@ -63,7 +62,7 @@ public class TestDefaultJWTEncryptionAndDecryptionService { private String issuer = "www.example.net"; private String subject = "example_user"; - private JWTClaimsSet claimsSet = new JWTClaimsSet(); + private JWTClaimsSet claimsSet = null; // Example data taken from Mike Jones's draft-ietf-jose-json-web-encryption-14 appendix examples private String compactSerializedJwe = "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ." + @@ -152,8 +151,10 @@ public void prepare() throws NoSuchAlgorithmException, InvalidKeySpecException, service_3 = new DefaultJWTEncryptionAndDecryptionService(keys_3); service_4 = new DefaultJWTEncryptionAndDecryptionService(keys_4); - claimsSet.setIssuer(issuer); - claimsSet.setSubject(subject); + claimsSet = new JWTClaimsSet.Builder() + .issuer(issuer) + .subject(subject) + .build(); // Key Store @@ -203,7 +204,7 @@ public void encryptThenDecrypt_RSA() throws ParseException { assertThat(encryptedJwt.getJWTClaimsSet(), nullValue()); service.decryptJwt(encryptedJwt); - ReadOnlyJWTClaimsSet resultClaims = encryptedJwt.getJWTClaimsSet(); + JWTClaimsSet resultClaims = encryptedJwt.getJWTClaimsSet(); assertEquals(claimsSet.getIssuer(), resultClaims.getIssuer()); assertEquals(claimsSet.getSubject(), resultClaims.getSubject()); @@ -231,7 +232,7 @@ public void encryptThenDecrypt_nullID() throws ParseException { assertThat(encryptedJwt.getJWTClaimsSet(), nullValue()); service.decryptJwt(encryptedJwt); - ReadOnlyJWTClaimsSet resultClaims = encryptedJwt.getJWTClaimsSet(); + JWTClaimsSet resultClaims = encryptedJwt.getJWTClaimsSet(); assertEquals(claimsSet.getIssuer(), resultClaims.getIssuer()); assertEquals(claimsSet.getSubject(), resultClaims.getSubject()); diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java index 120d3df304..ee43876def 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java @@ -206,22 +206,22 @@ public OAuth2AccessTokenEntity createAccessToken(OAuth2Authentication authentica private OAuth2RefreshTokenEntity createRefreshToken(ClientDetailsEntity client, AuthenticationHolderEntity authHolder) { OAuth2RefreshTokenEntity refreshToken = new OAuth2RefreshTokenEntity(); //refreshTokenFactory.createNewRefreshToken(); - JWTClaimsSet refreshClaims = new JWTClaimsSet(); + JWTClaimsSet.Builder refreshClaims = new JWTClaimsSet.Builder(); // make it expire if necessary if (client.getRefreshTokenValiditySeconds() != null) { Date expiration = new Date(System.currentTimeMillis() + (client.getRefreshTokenValiditySeconds() * 1000L)); refreshToken.setExpiration(expiration); - refreshClaims.setExpirationTime(expiration); + refreshClaims.expirationTime(expiration); } // set a random identifier - refreshClaims.setJWTID(UUID.randomUUID().toString()); + refreshClaims.jwtID(UUID.randomUUID().toString()); // TODO: add issuer fields, signature to JWT - PlainJWT refreshJwt = new PlainJWT(refreshClaims); + PlainJWT refreshJwt = new PlainJWT(refreshClaims.build()); refreshToken.setJwt(refreshJwt); //Add the authentication diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/token/JWTAssertionTokenGranter.java b/openid-connect-server/src/main/java/org/mitre/oauth2/token/JWTAssertionTokenGranter.java index 629b11d59d..69daa536df 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/token/JWTAssertionTokenGranter.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/token/JWTAssertionTokenGranter.java @@ -103,7 +103,7 @@ protected OAuth2AccessToken getAccessToken(ClientDetails client, TokenRequest to OAuth2AccessTokenEntity newIdTokenEntity = new OAuth2AccessTokenEntity(); // copy over all existing claims - JWTClaimsSet claims = new JWTClaimsSet(idToken.getJWTClaimsSet()); + JWTClaimsSet.Builder claims = new JWTClaimsSet.Builder(idToken.getJWTClaimsSet()); if (client instanceof ClientDetailsEntity) { @@ -112,7 +112,7 @@ protected OAuth2AccessToken getAccessToken(ClientDetails client, TokenRequest to // update expiration and issued-at claims if (clientEntity.getIdTokenValiditySeconds() != null) { Date expiration = new Date(System.currentTimeMillis() + (clientEntity.getIdTokenValiditySeconds() * 1000L)); - claims.setExpirationTime(expiration); + claims.expirationTime(expiration); newIdTokenEntity.setExpiration(expiration); } @@ -122,11 +122,11 @@ protected OAuth2AccessToken getAccessToken(ClientDetails client, TokenRequest to throw new BadCredentialsException("SEVERE: Client is not an instance of ClientDetailsEntity; JwtAssertionTokenGranter cannot process this request."); } - claims.setIssueTime(new Date()); - claims.setJWTID(UUID.randomUUID().toString()); // set a random NONCE in the middle of it + claims.issueTime(new Date()); + claims.jwtID(UUID.randomUUID().toString()); // set a random NONCE in the middle of it - SignedJWT newIdToken = new SignedJWT((JWSHeader) idToken.getHeader(), claims); + SignedJWT newIdToken = new SignedJWT((JWSHeader) idToken.getHeader(), claims.build()); jwtService.signJwt(newIdToken); newIdTokenEntity.setJwt(newIdToken); diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAuthenticationProvider.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAuthenticationProvider.java index 7ef8ab7184..84c0b7e17f 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAuthenticationProvider.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAuthenticationProvider.java @@ -44,7 +44,7 @@ import com.nimbusds.jose.JWSAlgorithm; import com.nimbusds.jwt.JWT; -import com.nimbusds.jwt.ReadOnlyJWTClaimsSet; +import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; /** @@ -88,7 +88,7 @@ public Authentication authenticate(Authentication authentication) throws Authent ClientDetailsEntity client = clientService.loadClientByClientId(jwtAuth.getClientId()); JWT jwt = jwtAuth.getJwt(); - ReadOnlyJWTClaimsSet jwtClaims = jwt.getJWTClaimsSet(); + JWTClaimsSet jwtClaims = jwt.getJWTClaimsSet(); // check the signature with nimbus if (jwt instanceof SignedJWT) { diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectOAuth2RequestFactory.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectOAuth2RequestFactory.java index 62a23d41cb..090ae0d9f8 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectOAuth2RequestFactory.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectOAuth2RequestFactory.java @@ -17,11 +17,23 @@ package org.mitre.openid.connect.request; +import static org.mitre.openid.connect.request.ConnectRequestParameters.CLAIMS; +import static org.mitre.openid.connect.request.ConnectRequestParameters.CLIENT_ID; +import static org.mitre.openid.connect.request.ConnectRequestParameters.DISPLAY; +import static org.mitre.openid.connect.request.ConnectRequestParameters.LOGIN_HINT; +import static org.mitre.openid.connect.request.ConnectRequestParameters.MAX_AGE; +import static org.mitre.openid.connect.request.ConnectRequestParameters.NONCE; +import static org.mitre.openid.connect.request.ConnectRequestParameters.PROMPT; +import static org.mitre.openid.connect.request.ConnectRequestParameters.REDIRECT_URI; +import static org.mitre.openid.connect.request.ConnectRequestParameters.REQUEST; +import static org.mitre.openid.connect.request.ConnectRequestParameters.RESPONSE_TYPE; +import static org.mitre.openid.connect.request.ConnectRequestParameters.SCOPE; +import static org.mitre.openid.connect.request.ConnectRequestParameters.STATE; + import java.text.ParseException; import java.util.Collections; import java.util.Map; import java.util.Set; -import java.util.UUID; import org.mitre.jwt.encryption.service.JWTEncryptionAndDecryptionService; import org.mitre.jwt.signer.service.JWTSigningAndValidationService; @@ -48,24 +60,11 @@ import com.nimbusds.jose.JWSAlgorithm; import com.nimbusds.jwt.EncryptedJWT; import com.nimbusds.jwt.JWT; +import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.JWTParser; import com.nimbusds.jwt.PlainJWT; -import com.nimbusds.jwt.ReadOnlyJWTClaimsSet; import com.nimbusds.jwt.SignedJWT; -import static org.mitre.openid.connect.request.ConnectRequestParameters.CLAIMS; -import static org.mitre.openid.connect.request.ConnectRequestParameters.CLIENT_ID; -import static org.mitre.openid.connect.request.ConnectRequestParameters.DISPLAY; -import static org.mitre.openid.connect.request.ConnectRequestParameters.LOGIN_HINT; -import static org.mitre.openid.connect.request.ConnectRequestParameters.MAX_AGE; -import static org.mitre.openid.connect.request.ConnectRequestParameters.NONCE; -import static org.mitre.openid.connect.request.ConnectRequestParameters.PROMPT; -import static org.mitre.openid.connect.request.ConnectRequestParameters.REDIRECT_URI; -import static org.mitre.openid.connect.request.ConnectRequestParameters.REQUEST; -import static org.mitre.openid.connect.request.ConnectRequestParameters.RESPONSE_TYPE; -import static org.mitre.openid.connect.request.ConnectRequestParameters.SCOPE; -import static org.mitre.openid.connect.request.ConnectRequestParameters.STATE; - @Component("connectOAuth2RequestFactory") public class ConnectOAuth2RequestFactory extends DefaultOAuth2RequestFactory { @@ -260,7 +259,7 @@ private void processRequestObject(String jwtString, AuthorizationRequest request // now that we've got the JWT, and it's been parsed, validated, and/or decrypted, we can process the claims - ReadOnlyJWTClaimsSet claims = jwt.getJWTClaimsSet(); + JWTClaimsSet claims = jwt.getJWTClaimsSet(); Set responseTypes = OAuth2Utils.parseParameterList(claims.getStringClaim(RESPONSE_TYPE)); if (responseTypes != null && !responseTypes.isEmpty()) { diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultOIDCTokenService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultOIDCTokenService.java index 0b9111e17c..c4df09183e 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultOIDCTokenService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultOIDCTokenService.java @@ -102,7 +102,7 @@ public OAuth2AccessTokenEntity createIdToken(ClientDetailsEntity client, OAuth2R OAuth2AccessTokenEntity idTokenEntity = new OAuth2AccessTokenEntity(); - JWTClaimsSet idClaims = new JWTClaimsSet(); + JWTClaimsSet.Builder idClaims = new JWTClaimsSet.Builder(); // if the auth time claim was explicitly requested OR if the client always wants the auth time, put it in if (request.getExtensions().containsKey("max_age") @@ -113,7 +113,7 @@ public OAuth2AccessTokenEntity createIdToken(ClientDetailsEntity client, OAuth2R Long authTimestamp = Long.parseLong((String) request.getExtensions().get(AuthenticationTimeStamper.AUTH_TIMESTAMP)); if (authTimestamp != null) { - idClaims.setClaim("auth_time", authTimestamp / 1000L); + idClaims.claim("auth_time", authTimestamp / 1000L); } } else { // we couldn't find the timestamp! @@ -121,22 +121,22 @@ public OAuth2AccessTokenEntity createIdToken(ClientDetailsEntity client, OAuth2R } } - idClaims.setIssueTime(issueTime); + idClaims.issueTime(issueTime); if (client.getIdTokenValiditySeconds() != null) { Date expiration = new Date(System.currentTimeMillis() + (client.getIdTokenValiditySeconds() * 1000L)); - idClaims.setExpirationTime(expiration); + idClaims.expirationTime(expiration); idTokenEntity.setExpiration(expiration); } - idClaims.setIssuer(configBean.getIssuer()); - idClaims.setSubject(sub); - idClaims.setAudience(Lists.newArrayList(client.getClientId())); - idClaims.setJWTID(UUID.randomUUID().toString()); // set a random NONCE in the middle of it + idClaims.issuer(configBean.getIssuer()); + idClaims.subject(sub); + idClaims.audience(Lists.newArrayList(client.getClientId())); + idClaims.jwtID(UUID.randomUUID().toString()); // set a random NONCE in the middle of it String nonce = (String)request.getExtensions().get("nonce"); if (!Strings.isNullOrEmpty(nonce)) { - idClaims.setCustomClaim("nonce", nonce); + idClaims.claim("nonce", nonce); } Set responseTypes = request.getResponseTypes(); @@ -144,7 +144,7 @@ public OAuth2AccessTokenEntity createIdToken(ClientDetailsEntity client, OAuth2R if (responseTypes.contains("token")) { // calculate the token hash Base64URL at_hash = IdTokenHashUtils.getAccessTokenHash(signingAlg, accessToken); - idClaims.setClaim("at_hash", at_hash); + idClaims.claim("at_hash", at_hash); } if (client.getIdTokenEncryptedResponseAlg() != null && !client.getIdTokenEncryptedResponseAlg().equals(Algorithm.NONE) @@ -155,7 +155,7 @@ public OAuth2AccessTokenEntity createIdToken(ClientDetailsEntity client, OAuth2R if (encrypter != null) { - EncryptedJWT idToken = new EncryptedJWT(new JWEHeader(client.getIdTokenEncryptedResponseAlg(), client.getIdTokenEncryptedResponseEnc()), idClaims); + EncryptedJWT idToken = new EncryptedJWT(new JWEHeader(client.getIdTokenEncryptedResponseAlg(), client.getIdTokenEncryptedResponseEnc()), idClaims.build()); encrypter.encryptJwt(idToken); @@ -171,7 +171,7 @@ public OAuth2AccessTokenEntity createIdToken(ClientDetailsEntity client, OAuth2R if (signingAlg.equals(Algorithm.NONE)) { // unsigned ID token - idToken = new PlainJWT(idClaims); + idToken = new PlainJWT(idClaims.build()); } else { @@ -184,20 +184,20 @@ public OAuth2AccessTokenEntity createIdToken(ClientDetailsEntity client, OAuth2R JWSHeader header = new JWSHeader(signingAlg, null, null, null, null, null, null, null, null, null, jwtService.getDefaultSignerKeyId(), null, null); - idToken = new SignedJWT(header, idClaims); + idToken = new SignedJWT(header, idClaims.build()); JWTSigningAndValidationService signer = symmetricCacheService.getSymmetricValidtor(client); // sign it with the client's secret signer.signJwt((SignedJWT) idToken); } else { - idClaims.setCustomClaim("kid", jwtService.getDefaultSignerKeyId()); + idClaims.claim("kid", jwtService.getDefaultSignerKeyId()); JWSHeader header = new JWSHeader(signingAlg, null, null, null, null, null, null, null, null, null, jwtService.getDefaultSignerKeyId(), null, null); - idToken = new SignedJWT(header, idClaims); + idToken = new SignedJWT(header, idClaims.build()); // sign it with the server's key jwtService.signJwt((SignedJWT) idToken); @@ -282,13 +282,13 @@ private OAuth2AccessTokenEntity createAssociatedToken(ClientDetailsEntity client authHolder = authenticationHolderRepository.save(authHolder); token.setAuthenticationHolder(authHolder); - JWTClaimsSet claims = new JWTClaimsSet(); - - claims.setAudience(Lists.newArrayList(client.getClientId())); - claims.setIssuer(configBean.getIssuer()); - claims.setIssueTime(new Date()); - claims.setExpirationTime(token.getExpiration()); - claims.setJWTID(UUID.randomUUID().toString()); // set a random NONCE in the middle of it + JWTClaimsSet claims = new JWTClaimsSet.Builder() + .audience(Lists.newArrayList(client.getClientId())) + .issuer(configBean.getIssuer()) + .issueTime(new Date()) + .expirationTime(token.getExpiration()) + .jwtID(UUID.randomUUID().toString()) // set a random NONCE in the middle of it + .build(); JWSAlgorithm signingAlg = jwtService.getDefaultSigningAlgorithm(); JWSHeader header = new JWSHeader(signingAlg, null, null, null, null, null, null, null, null, null, diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/ConnectTokenEnhancer.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/ConnectTokenEnhancer.java index 19d2cf0389..6b0cbc80a2 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/ConnectTokenEnhancer.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/ConnectTokenEnhancer.java @@ -88,17 +88,13 @@ public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentica String clientId = originalAuthRequest.getClientId(); ClientDetailsEntity client = clientService.loadClientByClientId(clientId); - JWTClaimsSet claims = new JWTClaimsSet(); - - claims.setAudience(Lists.newArrayList(clientId)); - - claims.setIssuer(configBean.getIssuer()); - - claims.setIssueTime(new Date()); - - claims.setExpirationTime(token.getExpiration()); - - claims.setJWTID(UUID.randomUUID().toString()); // set a random NONCE in the middle of it + JWTClaimsSet claims = new JWTClaimsSet.Builder() + .audience(Lists.newArrayList(clientId)) + .issuer(configBean.getIssuer()) + .issueTime(new Date()) + .expirationTime(token.getExpiration()) + .jwtID(UUID.randomUUID().toString()) // set a random NONCE in the middle of it + .build(); JWSAlgorithm signingAlg = jwtService.getDefaultSigningAlgorithm(); JWSHeader header = new JWSHeader(signingAlg, null, null, null, null, null, null, null, null, null, diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoJWTView.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoJWTView.java index 027ff0933b..114263a0ff 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoJWTView.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoJWTView.java @@ -98,15 +98,12 @@ protected void writeOut(JsonObject json, Map model, response.setContentType(JOSE_MEDIA_TYPE_VALUE); - JWTClaimsSet claims = JWTClaimsSet.parse(writer.toString()); - - claims.setAudience(Lists.newArrayList(client.getClientId())); - - claims.setIssuer(config.getIssuer()); - - claims.setIssueTime(new Date()); - - claims.setJWTID(UUID.randomUUID().toString()); // set a random NONCE in the middle of it + JWTClaimsSet claims = new JWTClaimsSet.Builder(JWTClaimsSet.parse(writer.toString())) + .audience(Lists.newArrayList(client.getClientId())) + .issuer(config.getIssuer()) + .issueTime(new Date()) + .jwtID(UUID.randomUUID().toString()) // set a random NONCE in the middle of it + .build(); if (client.getUserInfoEncryptedResponseAlg() != null && !client.getUserInfoEncryptedResponseAlg().equals(Algorithm.NONE) diff --git a/pom.xml b/pom.xml index 49c37479a3..d3c784f991 100644 --- a/pom.xml +++ b/pom.xml @@ -470,7 +470,7 @@ com.nimbusds nimbus-jose-jwt - 3.9 + 4.2 From 149e93e97023156bad3a817b374b84a04bbd388b Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 13 Oct 2015 11:57:41 -0400 Subject: [PATCH 108/465] Disabled broken crypto tests, pending #938 --- .../impl/TestDefaultJWTEncryptionAndDecryptionService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java b/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java index 69c0799137..75e4875cf3 100644 --- a/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java +++ b/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java @@ -167,7 +167,7 @@ public void prepare() throws NoSuchAlgorithmException, InvalidKeySpecException, } - @Test + //@Test public void decrypt_RSA() throws ParseException { service.setDefaultDecryptionKeyId(RSAkid); @@ -184,7 +184,7 @@ public void decrypt_RSA() throws ParseException { } - @Test + //@Test public void encryptThenDecrypt_RSA() throws ParseException { service.setDefaultDecryptionKeyId(RSAkid); @@ -212,7 +212,7 @@ public void encryptThenDecrypt_RSA() throws ParseException { // The same as encryptThenDecrypt_RSA() but relies on the key from the map - @Test + //@Test public void encryptThenDecrypt_nullID() throws ParseException { service.setDefaultDecryptionKeyId(null); From 9599642f3a8ce8954281eb0695a7286331ec67e0 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 13 Oct 2015 12:13:07 -0400 Subject: [PATCH 109/465] upgraded nimbus in uma module` --- .../uma/service/impl/DefaultUmaTokenService.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultUmaTokenService.java b/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultUmaTokenService.java index 9b3a0e6d06..4e2781b9b4 100644 --- a/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultUmaTokenService.java +++ b/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultUmaTokenService.java @@ -89,16 +89,16 @@ public OAuth2AccessTokenEntity createRequestingPartyToken(OAuth2Authentication o token.setPermissions(Sets.newHashSet(perm)); - JWTClaimsSet claims = new JWTClaimsSet(); + JWTClaimsSet.Builder claims = new JWTClaimsSet.Builder(); - claims.setAudience(Lists.newArrayList(ticket.getPermission().getResourceSet().getId().toString())); - claims.setIssuer(config.getIssuer()); - claims.setJWTID(UUID.randomUUID().toString()); + claims.audience(Lists.newArrayList(ticket.getPermission().getResourceSet().getId().toString())); + claims.issuer(config.getIssuer()); + claims.jwtID(UUID.randomUUID().toString()); if (config.getRqpTokenLifeTime() != null) { Date exp = new Date(System.currentTimeMillis() + config.getRqpTokenLifeTime() * 1000L); - claims.setExpirationTime(exp); + claims.expirationTime(exp); token.setExpiration(exp); } @@ -107,7 +107,7 @@ public OAuth2AccessTokenEntity createRequestingPartyToken(OAuth2Authentication o JWSHeader header = new JWSHeader(signingAlgorithm, null, null, null, null, null, null, null, null, null, jwtService.getDefaultSignerKeyId(), null, null); - SignedJWT signed = new SignedJWT(header, claims); + SignedJWT signed = new SignedJWT(header, claims.build()); jwtService.signJwt(signed); From 542afca4596886bc5fcd77f555f7df6b2b3c7fb3 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 13 Oct 2015 15:33:23 -0400 Subject: [PATCH 110/465] cleans duplicate access tokens from DB before other cleanup happens --- .../repository/OAuth2TokenRepository.java | 4 ++ .../impl/JpaOAuth2TokenRepository.java | 47 +++++++++++++++++++ .../DefaultOAuth2ProviderTokenService.java | 4 ++ 3 files changed, 55 insertions(+) diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2TokenRepository.java b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2TokenRepository.java index fec06224a9..3f32a938b9 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2TokenRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2TokenRepository.java @@ -62,4 +62,8 @@ public interface OAuth2TokenRepository { public Set getAccessTokensForResourceSet(ResourceSet rs); + public void clearDuplicateAccessTokens(); + + public void clearDuplicateRefreshTokens(); + } diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java index ad63dafab4..ced3166803 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java @@ -17,6 +17,7 @@ package org.mitre.oauth2.repository.impl; import java.text.ParseException; +import java.util.ArrayList; import java.util.Date; import java.util.LinkedHashSet; import java.util.List; @@ -24,7 +25,11 @@ import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; +import javax.persistence.Query; import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaDelete; +import javax.persistence.criteria.Root; import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.model.OAuth2AccessTokenEntity; @@ -32,6 +37,8 @@ import org.mitre.oauth2.repository.OAuth2TokenRepository; import org.mitre.uma.model.ResourceSet; import org.mitre.util.jpa.JpaUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; @@ -42,6 +49,8 @@ public class JpaOAuth2TokenRepository implements OAuth2TokenRepository { private static final int MAXEXPIREDRESULTS = 1000; + + private static final Logger logger = LoggerFactory.getLogger(JpaOAuth2TokenRepository.class); @PersistenceContext(unitName="defaultPersistenceUnit") private EntityManager manager; @@ -214,4 +223,42 @@ public Set getAccessTokensForResourceSet(ResourceSet rs return new LinkedHashSet<>(query.getResultList()); } + /* (non-Javadoc) + * @see org.mitre.oauth2.repository.OAuth2TokenRepository#clearDuplicateAccessTokens() + */ + @Override + @Transactional(value="defaultTransactionManager") + public void clearDuplicateAccessTokens() { + /* + * + * delete from access_token where token_value in + * (select token_value from (select token_value, count(*) as count from + * access_token group by token_value having count > 1) duplicate_tokens) + */ + + Query query = manager.createQuery("select a.jwt, count(1) as c from OAuth2AccessTokenEntity a GROUP BY a.jwt HAVING c > 1"); + List resultList = query.getResultList(); + List values = new ArrayList<>(); + for (Object[] r : resultList) { + logger.warn("Found duplicate: {}, {}", r[0], r[1]); + values.add((JWT) r[0]); + } + if (values.size() > 0) { + CriteriaBuilder cb = manager.getCriteriaBuilder(); + CriteriaDelete criteriaDelete = cb.createCriteriaDelete(OAuth2AccessTokenEntity.class); + Root root = criteriaDelete.from(OAuth2AccessTokenEntity.class); + criteriaDelete.where(root.get("jwt").in(values)); + int result = manager.createQuery(criteriaDelete).executeUpdate(); + logger.warn("Results from delete: {}", result); + } + } + + /* (non-Javadoc) + * @see org.mitre.oauth2.repository.OAuth2TokenRepository#clearDuplicateRefreshTokens() + */ + @Override + public void clearDuplicateRefreshTokens() { + + } + } diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java index ee43876def..f71b445743 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java @@ -424,6 +424,10 @@ public List getRefreshTokensForClient(ClientDetailsEnt @Override public void clearExpiredTokens() { logger.info("Cleaning out all expired tokens"); + + // get all the duplicated tokens first to maintain consistency + tokenRepository.clearDuplicateAccessTokens(); + tokenRepository.clearDuplicateRefreshTokens(); Collection accessTokens = getExpiredAccessTokens(); logger.info("Found " + accessTokens.size() + " expired access tokens"); From e1e892377fbcd6120ea0ce8a0c5f6e10569ad205 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 13 Oct 2015 15:38:07 -0400 Subject: [PATCH 111/465] added cleaner for duplicate refresh tokens --- .../impl/JpaOAuth2TokenRepository.java | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java index ced3166803..9e15556ec5 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java @@ -229,18 +229,12 @@ public Set getAccessTokensForResourceSet(ResourceSet rs @Override @Transactional(value="defaultTransactionManager") public void clearDuplicateAccessTokens() { - /* - * - * delete from access_token where token_value in - * (select token_value from (select token_value, count(*) as count from - * access_token group by token_value having count > 1) duplicate_tokens) - */ Query query = manager.createQuery("select a.jwt, count(1) as c from OAuth2AccessTokenEntity a GROUP BY a.jwt HAVING c > 1"); List resultList = query.getResultList(); List values = new ArrayList<>(); for (Object[] r : resultList) { - logger.warn("Found duplicate: {}, {}", r[0], r[1]); + logger.warn("Found duplicate access tokens: {}, {}", ((JWT)r[0]).serialize(), r[1]); values.add((JWT) r[0]); } if (values.size() > 0) { @@ -249,7 +243,7 @@ public void clearDuplicateAccessTokens() { Root root = criteriaDelete.from(OAuth2AccessTokenEntity.class); criteriaDelete.where(root.get("jwt").in(values)); int result = manager.createQuery(criteriaDelete).executeUpdate(); - logger.warn("Results from delete: {}", result); + logger.warn("Deleted {} duplicate access tokens", result); } } @@ -258,6 +252,21 @@ public void clearDuplicateAccessTokens() { */ @Override public void clearDuplicateRefreshTokens() { + Query query = manager.createQuery("select a.jwt, count(1) as c from OAuth2RefreshTokenEntity a GROUP BY a.jwt HAVING c > 1"); + List resultList = query.getResultList(); + List values = new ArrayList<>(); + for (Object[] r : resultList) { + logger.warn("Found duplicate refresh tokens: {}, {}", ((JWT)r[0]).serialize(), r[1]); + values.add((JWT) r[0]); + } + if (values.size() > 0) { + CriteriaBuilder cb = manager.getCriteriaBuilder(); + CriteriaDelete criteriaDelete = cb.createCriteriaDelete(OAuth2RefreshTokenEntity.class); + Root root = criteriaDelete.from(OAuth2RefreshTokenEntity.class); + criteriaDelete.where(root.get("jwt").in(values)); + int result = manager.createQuery(criteriaDelete).executeUpdate(); + logger.warn("Deleted {} duplicate refresh tokens", result); + } } From c9358f348a8ff1f40bb05eb782a39aedfbe90cf1 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 13 Oct 2015 16:59:11 -0400 Subject: [PATCH 112/465] added transactional annotations, finally closes #926 addresses #862 --- .../mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java index 9e15556ec5..7a23cd5ff2 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java @@ -231,6 +231,7 @@ public Set getAccessTokensForResourceSet(ResourceSet rs public void clearDuplicateAccessTokens() { Query query = manager.createQuery("select a.jwt, count(1) as c from OAuth2AccessTokenEntity a GROUP BY a.jwt HAVING c > 1"); + @SuppressWarnings("unchecked") List resultList = query.getResultList(); List values = new ArrayList<>(); for (Object[] r : resultList) { @@ -251,8 +252,10 @@ public void clearDuplicateAccessTokens() { * @see org.mitre.oauth2.repository.OAuth2TokenRepository#clearDuplicateRefreshTokens() */ @Override + @Transactional(value="defaultTransactionManager") public void clearDuplicateRefreshTokens() { Query query = manager.createQuery("select a.jwt, count(1) as c from OAuth2RefreshTokenEntity a GROUP BY a.jwt HAVING c > 1"); + @SuppressWarnings("unchecked") List resultList = query.getResultList(); List values = new ArrayList<>(); for (Object[] r : resultList) { From 8cc89e4e85b07bab853002714358c1222b3c161c Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 13 Oct 2015 17:04:36 -0400 Subject: [PATCH 113/465] made token fetching lazy-loaded --- .../main/java/org/mitre/openid/connect/model/ApprovedSite.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ApprovedSite.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ApprovedSite.java index d206e0cb26..0c644bbbb4 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ApprovedSite.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ApprovedSite.java @@ -229,7 +229,7 @@ public boolean isExpired() { } } - @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER) + @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY) @JoinColumn(name="approved_site_id") public Set getApprovedAccessTokens() { return approvedAccessTokens; From a5701f4ea36f47b27fb7adf4e7a56968b94abdc5 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 13 Oct 2015 17:28:40 -0400 Subject: [PATCH 114/465] limit client pagination to 10 pages at a time, closes #886 --- .../src/main/webapp/resources/js/client.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/client.js b/openid-connect-server-webapp/src/main/webapp/resources/js/client.js index 8d5633e560..770c6fa647 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/client.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/client.js @@ -516,6 +516,8 @@ var ClientListView = Backbone.View.extend({ $('.paginator', this.el).show(); $('.paginator', this.el).bootpag({ total: numPages, + maxVisible: 10, + leaps: false, page: 1 }); } else { From 96f4d5e8a897b1b804ae930d40b3db0ccfdf96c6 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 13 Oct 2015 18:08:56 -0400 Subject: [PATCH 115/465] fixed use of wrong constant, closes #940 --- .../openid/connect/token/TofuUserApprovalHandler.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/TofuUserApprovalHandler.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/TofuUserApprovalHandler.java index bda563654e..11e36a1f20 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/TofuUserApprovalHandler.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/TofuUserApprovalHandler.java @@ -16,6 +16,11 @@ *******************************************************************************/ package org.mitre.openid.connect.token; +import static org.mitre.openid.connect.request.ConnectRequestParameters.APPROVED_SITE; +import static org.mitre.openid.connect.request.ConnectRequestParameters.PROMPT; +import static org.mitre.openid.connect.request.ConnectRequestParameters.PROMPT_CONSENT; +import static org.mitre.openid.connect.request.ConnectRequestParameters.PROMPT_SEPARATOR; + import java.util.Calendar; import java.util.Collection; import java.util.Date; @@ -47,10 +52,6 @@ import com.google.common.base.Strings; import com.google.common.collect.Sets; -import static org.mitre.openid.connect.request.ConnectRequestParameters.APPROVED_SITE; -import static org.mitre.openid.connect.request.ConnectRequestParameters.PROMPT; -import static org.mitre.openid.connect.request.ConnectRequestParameters.PROMPT_SEPARATOR; - /** * Custom User Approval Handler implementation which uses a concept of a whitelist, * blacklist, and greylist. @@ -132,7 +133,7 @@ public AuthorizationRequest checkForPreApproval(AuthorizationRequest authorizati // find out if we're supposed to force a prompt on the user or not String prompt = (String) authorizationRequest.getExtensions().get(PROMPT); List prompts = Splitter.on(PROMPT_SEPARATOR).splitToList(Strings.nullToEmpty(prompt)); - if (!prompts.contains(PROMPT_SEPARATOR)) { + if (!prompts.contains(PROMPT_CONSENT)) { // if the prompt parameter is set to "consent" then we can't use approved sites or whitelisted sites // otherwise, we need to check them below From 6129cfa61a050ed2095b5e71e9f79737e17bfefd Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 13 Oct 2015 18:51:21 -0400 Subject: [PATCH 116/465] added scope-based authorities granter for introspections services, closes #835 --- ...eBasedIntrospectionAuthoritiesGranter.java | 72 ++++++++++++++++ ...eBasedIntrospectionAuthoritiesGranter.java | 85 +++++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/ScopeBasedIntrospectionAuthoritiesGranter.java create mode 100644 openid-connect-client/src/test/java/org/mitre/oauth2/introspectingfilter/service/impl/TestScopeBasedIntrospectionAuthoritiesGranter.java diff --git a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/ScopeBasedIntrospectionAuthoritiesGranter.java b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/ScopeBasedIntrospectionAuthoritiesGranter.java new file mode 100644 index 0000000000..5e29567ca7 --- /dev/null +++ b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/ScopeBasedIntrospectionAuthoritiesGranter.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright 2015 The MITRE Corporation + * and the MIT Kerberos and Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +package org.mitre.oauth2.introspectingfilter.service.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.mitre.oauth2.introspectingfilter.service.IntrospectionAuthorityGranter; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.oauth2.common.util.OAuth2Utils; + +import com.google.gson.JsonObject; + +/** + * @author jricher + * + */ +public class ScopeBasedIntrospectionAuthoritiesGranter implements IntrospectionAuthorityGranter { + + private List authorities = AuthorityUtils.createAuthorityList("ROLE_API"); + + /* (non-Javadoc) + * @see org.mitre.oauth2.introspectingfilter.IntrospectionAuthorityGranter#getAuthorities(net.minidev.json.JSONObject) + */ + @Override + public List getAuthorities(JsonObject introspectionResponse) { + List auth = new ArrayList<>(getAuthorities()); + + if (introspectionResponse.has("scope") && introspectionResponse.get("scope").isJsonPrimitive()) { + String scopeString = introspectionResponse.get("scope").getAsString(); + Set scopes = OAuth2Utils.parseParameterList(scopeString); + for (String scope : scopes) { + auth.add(new SimpleGrantedAuthority("OAUTH_SCOPE_" + scope)); + } + } + + return auth; + } + + /** + * @return the authorities + */ + public List getAuthorities() { + return authorities; + } + + /** + * @param authorities the authorities to set + */ + public void setAuthorities(List authorities) { + this.authorities = authorities; + } + +} diff --git a/openid-connect-client/src/test/java/org/mitre/oauth2/introspectingfilter/service/impl/TestScopeBasedIntrospectionAuthoritiesGranter.java b/openid-connect-client/src/test/java/org/mitre/oauth2/introspectingfilter/service/impl/TestScopeBasedIntrospectionAuthoritiesGranter.java new file mode 100644 index 0000000000..20952e79b6 --- /dev/null +++ b/openid-connect-client/src/test/java/org/mitre/oauth2/introspectingfilter/service/impl/TestScopeBasedIntrospectionAuthoritiesGranter.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright 2015 The MITRE Corporation + * and the MIT Kerberos and Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +package org.mitre.oauth2.introspectingfilter.service.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; + +import com.google.gson.JsonObject; + +import static org.junit.Assert.assertTrue; + +/** + * @author jricher + * + */ +public class TestScopeBasedIntrospectionAuthoritiesGranter { + + private JsonObject introspectionResponse; + + private ScopeBasedIntrospectionAuthoritiesGranter granter = new ScopeBasedIntrospectionAuthoritiesGranter(); + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + introspectionResponse = new JsonObject(); + } + + /** + * Test method for {@link org.mitre.oauth2.introspectingfilter.service.impl.ScopeBasedIntrospectionAuthoritiesGranter#getAuthorities(com.google.gson.JsonObject)}. + */ + @Test + public void testGetAuthoritiesJsonObject_withScopes() { + introspectionResponse.addProperty("scope", "foo bar baz batman"); + + List expected = new ArrayList<>(); + expected.add(new SimpleGrantedAuthority("ROLE_API")); + expected.add(new SimpleGrantedAuthority("OAUTH_SCOPE_foo")); + expected.add(new SimpleGrantedAuthority("OAUTH_SCOPE_bar")); + expected.add(new SimpleGrantedAuthority("OAUTH_SCOPE_baz")); + expected.add(new SimpleGrantedAuthority("OAUTH_SCOPE_batman")); + + List authorities = granter.getAuthorities(introspectionResponse); + + assertTrue(authorities.containsAll(expected)); + assertTrue(expected.containsAll(authorities)); + } + + /** + * Test method for {@link org.mitre.oauth2.introspectingfilter.service.impl.ScopeBasedIntrospectionAuthoritiesGranter#getAuthorities(com.google.gson.JsonObject)}. + */ + @Test + public void testGetAuthoritiesJsonObject_withoutScopes() { + + List expected = new ArrayList<>(); + expected.add(new SimpleGrantedAuthority("ROLE_API")); + + List authorities = granter.getAuthorities(introspectionResponse); + + assertTrue(authorities.containsAll(expected)); + assertTrue(expected.containsAll(authorities)); + } + +} From d96b2dc130b226b3138dd2b82d5c6d5712e9c56c Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 13 Oct 2015 18:56:44 -0400 Subject: [PATCH 117/465] [maven-release-plugin] prepare release mitreid-connect-1.2.2 --- openid-connect-client/pom.xml | 2 +- openid-connect-common/pom.xml | 2 +- openid-connect-server-webapp/pom.xml | 2 +- openid-connect-server/pom.xml | 2 +- pom.xml | 2 +- uma-server-webapp/pom.xml | 2 +- uma-server/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/openid-connect-client/pom.xml b/openid-connect-client/pom.xml index 67f4a39c12..f5ccf12dbf 100644 --- a/openid-connect-client/pom.xml +++ b/openid-connect-client/pom.xml @@ -21,7 +21,7 @@ openid-connect-parent org.mitre - 1.2.2-SNAPSHOT + 1.2.2 .. openid-connect-client diff --git a/openid-connect-common/pom.xml b/openid-connect-common/pom.xml index 1b9db7adf6..26f2748acd 100644 --- a/openid-connect-common/pom.xml +++ b/openid-connect-common/pom.xml @@ -21,7 +21,7 @@ openid-connect-parent org.mitre - 1.2.2-SNAPSHOT + 1.2.2 .. openid-connect-common diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index 354ddcc295..d80a1d9089 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.2.2-SNAPSHOT + 1.2.2 openid-connect-server-webapp war diff --git a/openid-connect-server/pom.xml b/openid-connect-server/pom.xml index ccd914b9ed..994bca762f 100644 --- a/openid-connect-server/pom.xml +++ b/openid-connect-server/pom.xml @@ -22,7 +22,7 @@ org.mitre openid-connect-parent - 1.2.2-SNAPSHOT + 1.2.2 .. diff --git a/pom.xml b/pom.xml index d3c784f991..652ca43497 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ 4.0.0 org.mitre openid-connect-parent - 1.2.2-SNAPSHOT + 1.2.2 MITREid Connect pom diff --git a/uma-server-webapp/pom.xml b/uma-server-webapp/pom.xml index 52d3c6323e..013fcdc057 100644 --- a/uma-server-webapp/pom.xml +++ b/uma-server-webapp/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.2.2-SNAPSHOT + 1.2.2 .. uma-server-webapp diff --git a/uma-server/pom.xml b/uma-server/pom.xml index de381d9570..204c042a07 100644 --- a/uma-server/pom.xml +++ b/uma-server/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.2.2-SNAPSHOT + 1.2.2 .. uma-server From 2deec98b58f3d7b35045e97eb67490b5852046be Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 13 Oct 2015 18:56:47 -0400 Subject: [PATCH 118/465] [maven-release-plugin] prepare for next development iteration --- openid-connect-client/pom.xml | 2 +- openid-connect-common/pom.xml | 2 +- openid-connect-server-webapp/pom.xml | 2 +- openid-connect-server/pom.xml | 2 +- pom.xml | 2 +- uma-server-webapp/pom.xml | 2 +- uma-server/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/openid-connect-client/pom.xml b/openid-connect-client/pom.xml index f5ccf12dbf..5d5c44beea 100644 --- a/openid-connect-client/pom.xml +++ b/openid-connect-client/pom.xml @@ -21,7 +21,7 @@ openid-connect-parent org.mitre - 1.2.2 + 1.2.3-SNAPSHOT .. openid-connect-client diff --git a/openid-connect-common/pom.xml b/openid-connect-common/pom.xml index 26f2748acd..95976ad02d 100644 --- a/openid-connect-common/pom.xml +++ b/openid-connect-common/pom.xml @@ -21,7 +21,7 @@ openid-connect-parent org.mitre - 1.2.2 + 1.2.3-SNAPSHOT .. openid-connect-common diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index d80a1d9089..2de8a407b5 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.2.2 + 1.2.3-SNAPSHOT openid-connect-server-webapp war diff --git a/openid-connect-server/pom.xml b/openid-connect-server/pom.xml index 994bca762f..fdbbba4a43 100644 --- a/openid-connect-server/pom.xml +++ b/openid-connect-server/pom.xml @@ -22,7 +22,7 @@ org.mitre openid-connect-parent - 1.2.2 + 1.2.3-SNAPSHOT .. diff --git a/pom.xml b/pom.xml index 652ca43497..8e2ebe909d 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ 4.0.0 org.mitre openid-connect-parent - 1.2.2 + 1.2.3-SNAPSHOT MITREid Connect pom diff --git a/uma-server-webapp/pom.xml b/uma-server-webapp/pom.xml index 013fcdc057..8b016c2f77 100644 --- a/uma-server-webapp/pom.xml +++ b/uma-server-webapp/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.2.2 + 1.2.3-SNAPSHOT .. uma-server-webapp diff --git a/uma-server/pom.xml b/uma-server/pom.xml index 204c042a07..d4dd12a3cd 100644 --- a/uma-server/pom.xml +++ b/uma-server/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.2.2 + 1.2.3-SNAPSHOT .. uma-server From f04face41e5cbe45e221aff9f4c6a8d785d95020 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 19 Oct 2015 14:16:40 -0400 Subject: [PATCH 119/465] updated to nimbus 4.3, check JCE policy and algorithm availability before running unit tests, closes #938 --- openid-connect-common/pom.xml | 4 ++ ...aultJWTEncryptionAndDecryptionService.java | 34 ++++++++-- ...aultJWTEncryptionAndDecryptionService.java | 62 +++++++++++++++---- pom.xml | 14 +++-- 4 files changed, 91 insertions(+), 23 deletions(-) diff --git a/openid-connect-common/pom.xml b/openid-connect-common/pom.xml index 95976ad02d..070f0001ce 100644 --- a/openid-connect-common/pom.xml +++ b/openid-connect-common/pom.xml @@ -82,6 +82,10 @@ com.fasterxml.jackson.core jackson-annotations + + org.bouncycastle + bcprov-jdk15on + jar diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/encryption/service/impl/DefaultJWTEncryptionAndDecryptionService.java b/openid-connect-common/src/main/java/org/mitre/jwt/encryption/service/impl/DefaultJWTEncryptionAndDecryptionService.java index e2d7ca0232..f9d08b74aa 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/encryption/service/impl/DefaultJWTEncryptionAndDecryptionService.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/encryption/service/impl/DefaultJWTEncryptionAndDecryptionService.java @@ -40,8 +40,13 @@ import com.nimbusds.jose.JWEObject; import com.nimbusds.jose.crypto.DirectDecrypter; import com.nimbusds.jose.crypto.DirectEncrypter; +import com.nimbusds.jose.crypto.ECDHDecrypter; +import com.nimbusds.jose.crypto.ECDHEncrypter; import com.nimbusds.jose.crypto.RSADecrypter; import com.nimbusds.jose.crypto.RSAEncrypter; +import com.nimbusds.jose.crypto.bc.BouncyCastleProviderSingleton; +import com.nimbusds.jose.jca.JCAContext; +import com.nimbusds.jose.jwk.ECKey; import com.nimbusds.jose.jwk.JWK; import com.nimbusds.jose.jwk.OctetSequenceKey; import com.nimbusds.jose.jwk.RSAKey; @@ -223,23 +228,40 @@ private void buildEncryptersAndDecrypters() throws NoSuchAlgorithmException, Inv if (jwk instanceof RSAKey) { // build RSA encrypters and decrypters - RSAEncrypter encrypter = new RSAEncrypter(((RSAKey) jwk).toRSAPublicKey()); // there should always at least be the public key + RSAEncrypter encrypter = new RSAEncrypter((RSAKey) jwk); // there should always at least be the public key + encrypter.getJCAContext().setProvider(BouncyCastleProviderSingleton.getInstance()); encrypters.put(id, encrypter); if (jwk.isPrivate()) { // we can decrypt! - RSADecrypter decrypter = new RSADecrypter(((RSAKey) jwk).toRSAPrivateKey()); + RSADecrypter decrypter = new RSADecrypter((RSAKey) jwk); + decrypter.getJCAContext().setProvider(BouncyCastleProviderSingleton.getInstance()); decrypters.put(id, decrypter); } else { logger.warn("No private key for key #" + jwk.getKeyID()); } - - // TODO: add support for EC keys + } else if (jwk instanceof ECKey) { + + // build EC Encrypters and decrypters + + ECDHEncrypter encrypter = new ECDHEncrypter((ECKey) jwk); + encrypter.getJCAContext().setProvider(BouncyCastleProviderSingleton.getInstance()); + encrypters.put(id, encrypter); + + if (jwk.isPrivate()) { // we can decrypt too + ECDHDecrypter decrypter = new ECDHDecrypter((ECKey) jwk); + decrypter.getJCAContext().setProvider(BouncyCastleProviderSingleton.getInstance()); + decrypters.put(id, decrypter); + } else { + logger.warn("No private key for key # " + jwk.getKeyID()); + } } else if (jwk instanceof OctetSequenceKey) { // build symmetric encrypters and decrypters - DirectEncrypter encrypter = new DirectEncrypter(((OctetSequenceKey) jwk).toByteArray()); - DirectDecrypter decrypter = new DirectDecrypter(((OctetSequenceKey) jwk).toByteArray()); + DirectEncrypter encrypter = new DirectEncrypter((OctetSequenceKey) jwk); + encrypter.getJCAContext().setProvider(BouncyCastleProviderSingleton.getInstance()); + DirectDecrypter decrypter = new DirectDecrypter((OctetSequenceKey) jwk); + decrypter.getJCAContext().setProvider(BouncyCastleProviderSingleton.getInstance()); encrypters.put(id, encrypter); decrypters.put(id, decrypter); diff --git a/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java b/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java index 75e4875cf3..807f5f7591 100644 --- a/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java +++ b/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java @@ -23,9 +23,16 @@ import java.util.List; import java.util.Map; +import javax.crypto.Cipher; + +import org.junit.Assume; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.mitre.jose.keystore.JWKSetKeyStore; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.collect.ImmutableMap; import com.nimbusds.jose.EncryptionMethod; @@ -33,6 +40,7 @@ import com.nimbusds.jose.JWEAlgorithm; import com.nimbusds.jose.JWEHeader; import com.nimbusds.jose.JWEObject; +import com.nimbusds.jose.jca.JCASupport; import com.nimbusds.jose.jwk.JWK; import com.nimbusds.jose.jwk.JWKSet; import com.nimbusds.jose.jwk.KeyUse; @@ -57,14 +65,19 @@ */ public class TestDefaultJWTEncryptionAndDecryptionService { + + private static Logger logger = LoggerFactory.getLogger(TestDefaultJWTEncryptionAndDecryptionService.class); private String plainText = "The true sign of intelligence is not knowledge but imagination."; private String issuer = "www.example.net"; private String subject = "example_user"; private JWTClaimsSet claimsSet = null; + + @Rule + public ExpectedException exception = ExpectedException.none(); - // Example data taken from Mike Jones's draft-ietf-jose-json-web-encryption-14 appendix examples + // Example data taken from rfc7516 appendix A private String compactSerializedJwe = "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ." + "OKOawDo13gRp2ojaHV7LFpZcgV7T6DVZKTyKOMTYUmKoTCVJRgckCL9kiMT03JGe" + "ipsEdY3mx_etLbbWSrFr05kLzcSr4qKAq7YN7e9jwQRb23nfa6c9d-StnImGyFDb" + @@ -167,9 +180,13 @@ public void prepare() throws NoSuchAlgorithmException, InvalidKeySpecException, } - //@Test - public void decrypt_RSA() throws ParseException { + @Test + public void decrypt_RSA() throws ParseException, NoSuchAlgorithmException { + Assume.assumeTrue(JCASupport.isSupported(JWEAlgorithm.RSA_OAEP) // check for algorithm support + && JCASupport.isSupported(EncryptionMethod.A256GCM) + && Cipher.getMaxAllowedKeyLength("RC5") >= 256); // check for unlimited crypto strength + service.setDefaultDecryptionKeyId(RSAkid); service.setDefaultEncryptionKeyId(RSAkid); @@ -184,9 +201,13 @@ public void decrypt_RSA() throws ParseException { } - //@Test - public void encryptThenDecrypt_RSA() throws ParseException { + @Test + public void encryptThenDecrypt_RSA() throws ParseException, NoSuchAlgorithmException { + Assume.assumeTrue(JCASupport.isSupported(JWEAlgorithm.RSA_OAEP) // check for algorithm support + && JCASupport.isSupported(EncryptionMethod.A256GCM) + && Cipher.getMaxAllowedKeyLength("RC5") >= 256); // check for unlimited crypto strength + service.setDefaultDecryptionKeyId(RSAkid); service.setDefaultEncryptionKeyId(RSAkid); @@ -212,9 +233,13 @@ public void encryptThenDecrypt_RSA() throws ParseException { // The same as encryptThenDecrypt_RSA() but relies on the key from the map - //@Test - public void encryptThenDecrypt_nullID() throws ParseException { - + @Test + public void encryptThenDecrypt_nullID() throws ParseException, NoSuchAlgorithmException { + + Assume.assumeTrue(JCASupport.isSupported(JWEAlgorithm.RSA_OAEP) // check for algorithm support + && JCASupport.isSupported(EncryptionMethod.A256GCM) + && Cipher.getMaxAllowedKeyLength("RC5") >= 256); // check for unlimited crypto strength + service.setDefaultDecryptionKeyId(null); service.setDefaultEncryptionKeyId(null); @@ -239,9 +264,15 @@ public void encryptThenDecrypt_nullID() throws ParseException { } - @Test(expected=IllegalStateException.class) - public void encrypt_nullID_oneKey() { + @Test + public void encrypt_nullID_oneKey() throws NoSuchAlgorithmException { + + Assume.assumeTrue(JCASupport.isSupported(JWEAlgorithm.RSA_OAEP) // check for algorithm support + && JCASupport.isSupported(EncryptionMethod.A256GCM) + && Cipher.getMaxAllowedKeyLength("RC5") >= 256); // check for unlimited crypto strength + exception.expect(IllegalStateException.class); + service_2.setDefaultEncryptionKeyId(null); assertEquals(null, service_2.getDefaultEncryptionKeyId()); @@ -254,9 +285,16 @@ public void encrypt_nullID_oneKey() { } - @Test(expected=IllegalStateException.class) - public void decrypt_nullID() throws ParseException { + @Test + public void decrypt_nullID() throws ParseException, NoSuchAlgorithmException { + + Assume.assumeTrue(JCASupport.isSupported(JWEAlgorithm.RSA_OAEP) // check for algorithm support + && JCASupport.isSupported(EncryptionMethod.A256GCM) + && Cipher.getMaxAllowedKeyLength("RC5") >= 256); // check for unlimited crypto strength + + exception.expect(IllegalStateException.class); + service_2.setDefaultEncryptionKeyId(RSAkid); service_2.setDefaultDecryptionKeyId(null); diff --git a/pom.xml b/pom.xml index 8e2ebe909d..b3856f198e 100644 --- a/pom.xml +++ b/pom.xml @@ -335,6 +335,11 @@ javax.persistence 2.1.0 + + com.zaxxer + HikariCP + 2.4.1 + @@ -470,13 +475,12 @@ com.nimbusds nimbus-jose-jwt - 4.2 + 4.3 - - com.zaxxer - HikariCP - 2.4.1 + org.bouncycastle + bcprov-jdk15on + [1.52,] From 5f24685f1786a4556ba8e101e1ae1028d1e89ec7 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 19 Oct 2015 15:00:41 -0400 Subject: [PATCH 120/465] removed problematic (and not very useful) unit test, closes #742 --- .../org/mitre/jose/TestJWKSetKeyStore.java | 31 ------------------- 1 file changed, 31 deletions(-) diff --git a/openid-connect-common/src/test/java/org/mitre/jose/TestJWKSetKeyStore.java b/openid-connect-common/src/test/java/org/mitre/jose/TestJWKSetKeyStore.java index 611d57ad7d..a2dd2d4435 100644 --- a/openid-connect-common/src/test/java/org/mitre/jose/TestJWKSetKeyStore.java +++ b/openid-connect-common/src/test/java/org/mitre/jose/TestJWKSetKeyStore.java @@ -160,37 +160,6 @@ public void ksEmptyConstructorkLoc() { File file = new File(ks_file); - /* First, test with file without "read" permission */ - - boolean set = false; - - if (file.exists()) { - set = file.setReadable(false); - } - - // skip this part of the test on systems that don't allow the settable function, like Windows - if (set) { - - Resource loc_noread = new FileSystemResource(file); - assertTrue(loc_noread.exists()); - // assertTrue(!loc_noread.isReadable()); - - boolean thrown = false; - try { - ks.setLocation(loc_noread); - } catch (IllegalArgumentException e) { - thrown = true; - } - assertTrue(thrown); - - /* Now, make cache file readable */ - - if (file.exists()) { - file.setReadable(true); - } - - } - Resource loc = new FileSystemResource(file); assertTrue(loc.exists()); assertTrue(loc.isReadable()); From abff7421c1872f4b5c53d724ea389b4a87052ad8 Mon Sep 17 00:00:00 2001 From: Mark Janssen Date: Thu, 15 Oct 2015 22:27:26 +0200 Subject: [PATCH 121/465] Upgrade to Spring Framework 4.1.8 http://spring.io/blog/2015/10/15/spring-framework-4-2-2-4-1-8-and-3-2-15-available-now --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b3856f198e..f745e8f9a9 100644 --- a/pom.xml +++ b/pom.xml @@ -259,7 +259,7 @@ org.springframework spring-framework-bom - 4.1.7.RELEASE + 4.1.8.RELEASE pom import From a3d01727f96da2e36a4820c82a62020fbdcd9538 Mon Sep 17 00:00:00 2001 From: Mark Janssen Date: Tue, 20 Oct 2015 22:33:37 +0200 Subject: [PATCH 122/465] Make FILTER_PROCESSES_URL public Currently hardcoded in the filter and the client's Spring Security config; would be nicer to reference the value instead. https://github.com/mitreid-connect/simple-web-app/blob/c5e70ebd5c28de2cce81d106435ae11925424a5f/src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml#L54 --- .../mitre/openid/connect/client/OIDCAuthenticationFilter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java index 9af8f5edf8..ce0a109206 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java @@ -96,7 +96,7 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi protected static final String TARGET_SESSION_VARIABLE = "target"; protected final static int HTTP_SOCKET_TIMEOUT = 30000; - protected final static String FILTER_PROCESSES_URL = "/openid_connect_login"; + public final static String FILTER_PROCESSES_URL = "/openid_connect_login"; // Allow for time sync issues by having a window of X seconds. private int timeSkewAllowance = 300; From 4c1e6866ce73bfc9864e1870d1b5c4f1ff18a5f3 Mon Sep 17 00:00:00 2001 From: Mark Janssen Date: Sun, 25 Oct 2015 19:11:41 +0100 Subject: [PATCH 123/465] Filter only `*.tag` files Instead of excluding all binary files, just filter `*.tag` files. http://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html --- openid-connect-server-webapp/pom.xml | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index 2de8a407b5..bc45831a6d 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -40,23 +40,20 @@ maven-war-plugin openid-connect-server-webapp - - gif - ico - jpg - png - pdf - eot - woff - ttf - svg - jwks - json - src/main/webapp true + + **/*.tag + + + + src/main/webapp + false + + **/*.tag + From 6d2b73a7ef1119afd663026834b27903de2aab97 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 23 Nov 2015 21:25:02 -0500 Subject: [PATCH 124/465] added JSPs to filter --- openid-connect-server-webapp/pom.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index bc45831a6d..e38161ebc6 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -46,6 +46,7 @@ true **/*.tag + **/*.jsp @@ -53,6 +54,7 @@ false **/*.tag + **/*.jsp From 4f9ea0b474ae481fa20365744841a4c0db0c9a05 Mon Sep 17 00:00:00 2001 From: Mark Janssen Date: Sun, 25 Oct 2015 19:17:58 +0100 Subject: [PATCH 125/465] Improve state handling in handleAuthorizationCodeResponse Fail fast when there is no state in session, e.g. because the session cookie was removed. Resolves #949 --- .../openid/connect/client/OIDCAuthenticationFilter.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java index ce0a109206..dbf0ab50fd 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java @@ -286,11 +286,9 @@ protected Authentication handleAuthorizationCodeResponse(HttpServletRequest requ // check for state, if it doesn't match we bail early String storedState = getStoredState(session); - if (!Strings.isNullOrEmpty(storedState)) { - String state = request.getParameter("state"); - if (!storedState.equals(state)) { - throw new AuthenticationServiceException("State parameter mismatch on return. Expected " + storedState + " got " + state); - } + String requestState = request.getParameter("state"); + if (storedState == null || !storedState.equals(requestState)) { + throw new AuthenticationServiceException("State parameter mismatch on return. Expected " + storedState + " got " + requestState); } // look up the issuer that we set out to talk to From f27673a5f5e6108766420b3c085e3e86b1dbd590 Mon Sep 17 00:00:00 2001 From: Mark Janssen Date: Sun, 25 Oct 2015 21:41:18 +0100 Subject: [PATCH 126/465] Align user profile claims Especially helps when `
` collapses due to an empty claim value. --- .../src/main/webapp/resources/css/mitreid-connect.css | 7 ++++++- .../src/main/webapp/resources/template/admin.html | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/openid-connect-server-webapp/src/main/webapp/resources/css/mitreid-connect.css b/openid-connect-server-webapp/src/main/webapp/resources/css/mitreid-connect.css index 066d8fa87b..0a67c56a43 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/css/mitreid-connect.css +++ b/openid-connect-server-webapp/src/main/webapp/resources/css/mitreid-connect.css @@ -180,4 +180,9 @@ h1,label { line-height: 20px; vertical-align: middle; margin: 0; -} \ No newline at end of file +} + +/* User profile claims alignment */ +.user-profile dd, .user-profile dt { + height: 20px; +} diff --git a/openid-connect-server-webapp/src/main/webapp/resources/template/admin.html b/openid-connect-server-webapp/src/main/webapp/resources/template/admin.html index 48d74d16d8..e36f5e5f3f 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/template/admin.html +++ b/openid-connect-server-webapp/src/main/webapp/resources/template/admin.html @@ -96,7 +96,7 @@
Your user profile has the following information:
-
+ @@ -109,4 +109,4 @@ <%- category %>.<% } %><%- key %>
<%- value %>
- \ No newline at end of file + From dce80d488b7806fb43f27d6567a1d401883bf390 Mon Sep 17 00:00:00 2001 From: Mark Janssen Date: Sun, 25 Oct 2015 22:04:57 +0100 Subject: [PATCH 127/465] Clean up ScopeClaimTranslationService `getFieldNameForClaim` method is never used. --- .../service/ScopeClaimTranslationService.java | 4 +-- .../DefaultScopeClaimTranslationService.java | 36 ------------------- 2 files changed, 1 insertion(+), 39 deletions(-) diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/ScopeClaimTranslationService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/ScopeClaimTranslationService.java index 755eb8fdc8..6b38453659 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/ScopeClaimTranslationService.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/ScopeClaimTranslationService.java @@ -31,6 +31,4 @@ public interface ScopeClaimTranslationService { public Set getClaimsForScopeSet(Set scopes); - public String getFieldNameForClaim(String claim); - -} \ No newline at end of file +} diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultScopeClaimTranslationService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultScopeClaimTranslationService.java index 45b083739a..53fddd4d80 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultScopeClaimTranslationService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultScopeClaimTranslationService.java @@ -37,13 +37,11 @@ public class DefaultScopeClaimTranslationService implements ScopeClaimTranslationService { private SetMultimap scopesToClaims = HashMultimap.create(); - private Map claimsToFields = Maps.newHashMap(); /** * Default constructor; initializes scopesToClaims map */ public DefaultScopeClaimTranslationService() { - scopesToClaims.put("openid", "sub"); scopesToClaims.put("profile", "name"); @@ -68,32 +66,6 @@ public DefaultScopeClaimTranslationService() { scopesToClaims.put("phone", "phone_number_verified"); scopesToClaims.put("address", "address"); - - claimsToFields.put("sub", "sub"); - - claimsToFields.put("name", "name"); - claimsToFields.put("preferred_username", "preferredUsername"); - claimsToFields.put("given_name", "givenName"); - claimsToFields.put("family_name", "familyName"); - claimsToFields.put("middle_name", "middleName"); - claimsToFields.put("nickname", "nickname"); - claimsToFields.put("profile", "profile"); - claimsToFields.put("picture", "picture"); - claimsToFields.put("website", "website"); - claimsToFields.put("gender", "gender"); - claimsToFields.put("zone_info", "zoneinfo"); - claimsToFields.put("locale", "locale"); - claimsToFields.put("updated_at", "updatedTime"); - claimsToFields.put("birthdate", "birthdate"); - - claimsToFields.put("email", "email"); - claimsToFields.put("email_verified", "emailVerified"); - - claimsToFields.put("phone_number", "phoneNumber"); - claimsToFields.put("phone_number_verified", "phoneNumberVerified"); - - claimsToFields.put("address", "address"); - } /* (non-Javadoc) @@ -120,12 +92,4 @@ public Set getClaimsForScopeSet(Set scopes) { return result; } - /* (non-Javadoc) - * @see org.mitre.openid.connect.service.ScopeClaimTranslationService#getFieldNameForClaim(java.lang.String) - */ - @Override - public String getFieldNameForClaim(String claim) { - return claimsToFields.get(claim); - } - } From a80953a2d4b0037729061f8ad787fce31f366636 Mon Sep 17 00:00:00 2001 From: Cosmin Cojocar Date: Tue, 29 Sep 2015 15:19:02 +0200 Subject: [PATCH 128/465] Allow both flows authorization code and client credentials. This scenario might be found when the same client supports user authentication as well as service to service authentication. Such a client is trusted (whitelisted). --- .../DynamicClientRegistrationEndpoint.java | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java index b542d30d85..814db571a1 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java @@ -394,9 +394,11 @@ private ClientDetailsEntity validateGrantTypes(ClientDetailsEntity newClient) th // set default grant types if needed if (newClient.getGrantTypes() == null || newClient.getGrantTypes().isEmpty()) { if (newClient.getScope().contains("offline_access")) { // client asked for offline access - newClient.setGrantTypes(Sets.newHashSet("authorization_code", "refresh_token")); // allow authorization code and refresh token grant types by default + // allow authorization code, client credentials and refresh token grant types by default + newClient.setGrantTypes(Sets.newHashSet("authorization_code", "client_credentials", "refresh_token")); } else { - newClient.setGrantTypes(Sets.newHashSet("authorization_code")); // allow authorization code grant type by default + // allow authorization code grant type by default + newClient.setGrantTypes(Sets.newHashSet("authorization_code", "client_credentials")); } } @@ -418,8 +420,7 @@ private ClientDetailsEntity validateGrantTypes(ClientDetailsEntity newClient) th if (newClient.getGrantTypes().contains("authorization_code")) { // check for incompatible grants - if (newClient.getGrantTypes().contains("implicit") || - newClient.getGrantTypes().contains("client_credentials")) { + if (newClient.getGrantTypes().contains("implicit")) { // return an error, you can't have these grant types together throw new ValidationException("invalid_client_metadata", "Incompatible grant types requested: " + newClient.getGrantTypes(), HttpStatus.BAD_REQUEST); } @@ -430,15 +431,12 @@ private ClientDetailsEntity validateGrantTypes(ClientDetailsEntity newClient) th } newClient.getResponseTypes().add("code"); - - } if (newClient.getGrantTypes().contains("implicit")) { // check for incompatible grants - if (newClient.getGrantTypes().contains("authorization_code") || - newClient.getGrantTypes().contains("client_credentials")) { + if (newClient.getGrantTypes().contains("authorization_code")) { // return an error, you can't have these grant types together throw new ValidationException("invalid_client_metadata", "Incompatible grant types requested: " + newClient.getGrantTypes(), HttpStatus.BAD_REQUEST); } @@ -456,14 +454,7 @@ private ClientDetailsEntity validateGrantTypes(ClientDetailsEntity newClient) th } if (newClient.getGrantTypes().contains("client_credentials")) { - - // check for incompatible grants - if (newClient.getGrantTypes().contains("authorization_code") || - newClient.getGrantTypes().contains("implicit")) { - // return an error, you can't have these grant types together - throw new ValidationException("invalid_client_metadata", "Incompatible grant types requested: " + newClient.getGrantTypes(), HttpStatus.BAD_REQUEST); - } - + if (!newClient.getResponseTypes().isEmpty()) { // return an error, you can't have this grant type and response type together throw new ValidationException("invalid_client_metadata", "Incompatible response types requested: " + newClient.getGrantTypes() + " / " + newClient.getResponseTypes(), HttpStatus.BAD_REQUEST); From 7b34a666d9bf2c79d6a587c262d9798dffff29f4 Mon Sep 17 00:00:00 2001 From: Cosmin Cojocar Date: Mon, 5 Oct 2015 11:56:25 +0200 Subject: [PATCH 129/465] Make the dual client support configurable --- .../config/ConfigurationPropertiesBean.java | 18 ++++++++++++- .../src/main/webapp/WEB-INF/server-config.xml | 4 +++ .../DynamicClientRegistrationEndpoint.java | 26 ++++++++++++++----- 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationPropertiesBean.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationPropertiesBean.java index f9bf1364ff..4ce9ed6158 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationPropertiesBean.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationPropertiesBean.java @@ -56,7 +56,9 @@ public class ConfigurationPropertiesBean { private Locale locale = Locale.ENGLISH; // we default to the english translation - public ConfigurationPropertiesBean() { + public boolean dualClient = false; + + public ConfigurationPropertiesBean() { } @@ -168,4 +170,18 @@ public Locale getLocale() { public void setLocale(Locale locale) { this.locale = locale; } + + /** + * @return true if dual client is configured, otherwise false + */ + public boolean isDualClient() { + return dualClient; + } + + /** + * @param dualClient the dual client configuration + */ + public void setDualClient(boolean dualClient) { + this.dualClient = dualClient; + } } diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/server-config.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/server-config.xml index b17a1496a0..58cf5f1558 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/server-config.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/server-config.xml @@ -49,6 +49,10 @@ + + + diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java index 814db571a1..96012cf5eb 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java @@ -394,11 +394,14 @@ private ClientDetailsEntity validateGrantTypes(ClientDetailsEntity newClient) th // set default grant types if needed if (newClient.getGrantTypes() == null || newClient.getGrantTypes().isEmpty()) { if (newClient.getScope().contains("offline_access")) { // client asked for offline access - // allow authorization code, client credentials and refresh token grant types by default - newClient.setGrantTypes(Sets.newHashSet("authorization_code", "client_credentials", "refresh_token")); + newClient.setGrantTypes(Sets.newHashSet("authorization_code", "refresh_token")); // allow authorization code and refresh token grant types by default } else { - // allow authorization code grant type by default - newClient.setGrantTypes(Sets.newHashSet("authorization_code", "client_credentials")); + newClient.setGrantTypes(Sets.newHashSet("authorization_code")); // allow authorization code grant type by default + } + if (config.isDualClient()) { + Set extendedGrandTypes = newClient.getGrantTypes(); + extendedGrandTypes.add("client_credentials"); + newClient.setGrantTypes(extendedGrandTypes); } } @@ -420,7 +423,8 @@ private ClientDetailsEntity validateGrantTypes(ClientDetailsEntity newClient) th if (newClient.getGrantTypes().contains("authorization_code")) { // check for incompatible grants - if (newClient.getGrantTypes().contains("implicit")) { + if (newClient.getGrantTypes().contains("implicit") || + (!config.isDualClient() && newClient.getGrantTypes().contains("client_credentials"))) { // return an error, you can't have these grant types together throw new ValidationException("invalid_client_metadata", "Incompatible grant types requested: " + newClient.getGrantTypes(), HttpStatus.BAD_REQUEST); } @@ -436,7 +440,8 @@ private ClientDetailsEntity validateGrantTypes(ClientDetailsEntity newClient) th if (newClient.getGrantTypes().contains("implicit")) { // check for incompatible grants - if (newClient.getGrantTypes().contains("authorization_code")) { + if (newClient.getGrantTypes().contains("authorization_code") || + (!config.isDualClient() && newClient.getGrantTypes().contains("client_credentials"))) { // return an error, you can't have these grant types together throw new ValidationException("invalid_client_metadata", "Incompatible grant types requested: " + newClient.getGrantTypes(), HttpStatus.BAD_REQUEST); } @@ -454,7 +459,14 @@ private ClientDetailsEntity validateGrantTypes(ClientDetailsEntity newClient) th } if (newClient.getGrantTypes().contains("client_credentials")) { - + + // check for incompatible grants + if (!config.isDualClient() && + (newClient.getGrantTypes().contains("authorization_code") || newClient.getGrantTypes().contains("implicit"))) { + // return an error, you can't have these grant types together + throw new ValidationException("invalid_client_metadata", "Incompatible grant types requested: " + newClient.getGrantTypes(), HttpStatus.BAD_REQUEST); + } + if (!newClient.getResponseTypes().isEmpty()) { // return an error, you can't have this grant type and response type together throw new ValidationException("invalid_client_metadata", "Incompatible response types requested: " + newClient.getGrantTypes() + " / " + newClient.getResponseTypes(), HttpStatus.BAD_REQUEST); From 70751a3d4aaf197a8ee655111342c3fe32d6ff7e Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 24 Nov 2015 12:17:32 -0500 Subject: [PATCH 130/465] updated configuration to comment out optional property value in example --- .../src/main/webapp/WEB-INF/server-config.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/server-config.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/server-config.xml index 58cf5f1558..91a0c67ca6 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/server-config.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/server-config.xml @@ -43,15 +43,15 @@ - + - + - + From e255fc1a10f430a23ebf8c874c24ea26d3fd42d3 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 24 Nov 2015 14:15:22 -0500 Subject: [PATCH 131/465] change default behavior of message source, closes #964 --- .../src/main/webapp/WEB-INF/application-context.xml | 1 + .../openid/connect/config/JsonMessageSource.java | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/application-context.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/application-context.xml index dbdf1f7f4c..d616fa1bf8 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/application-context.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/application-context.xml @@ -200,6 +200,7 @@ + diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/config/JsonMessageSource.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/config/JsonMessageSource.java index edf7fcb40a..ef000507f8 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/config/JsonMessageSource.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/config/JsonMessageSource.java @@ -66,12 +66,13 @@ protected MessageFormat resolveCode(String code, Locale locale) { } if (value == null) { - value = code; + // if it's still null, return null + return null; + } else { + // otherwise format the message + return new MessageFormat(value, locale); } - - MessageFormat mf = new MessageFormat(value, locale); - - return mf; + } /** From 2496dc114c46a4ae5963e95ff73c85de8ff6c678 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 24 Nov 2015 20:33:03 -0500 Subject: [PATCH 132/465] allow language system to be loaded from multiple files. closes #817 closes #876 --- .../config/ConfigurationPropertiesBean.java | 43 +++++++++++- .../ConfigurationPropertiesBeanTest.java | 12 ++-- .../src/main/webapp/WEB-INF/server-config.xml | 13 +++- .../src/main/webapp/WEB-INF/tags/header.tag | 7 +- .../connect/config/JsonMessageSource.java | 69 ++++++++++++++----- 5 files changed, 117 insertions(+), 27 deletions(-) diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationPropertiesBean.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationPropertiesBean.java index 4ce9ed6158..f03df8d671 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationPropertiesBean.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationPropertiesBean.java @@ -16,6 +16,7 @@ *******************************************************************************/ package org.mitre.openid.connect.config; +import java.util.List; import java.util.Locale; import javax.annotation.PostConstruct; @@ -25,6 +26,9 @@ import org.springframework.beans.factory.BeanCreationException; import org.springframework.util.StringUtils; +import com.google.common.collect.Lists; +import com.google.gson.Gson; + /** @@ -55,6 +59,8 @@ public class ConfigurationPropertiesBean { private boolean forceHttps = false; // by default we just log a warning for HTTPS deployment private Locale locale = Locale.ENGLISH; // we default to the english translation + + private List languageNamespaces = Lists.newArrayList("messages"); public boolean dualClient = false; @@ -67,7 +73,7 @@ public ConfigurationPropertiesBean() { * @throws HttpsUrlRequiredException */ @PostConstruct - public void checkForHttps() { + public void checkConfigConsistency() { if (!StringUtils.startsWithIgnoreCase(issuer, "https")) { if (this.forceHttps) { logger.error("Configured issuer url is not using https scheme. Server will be shut down!"); @@ -77,6 +83,10 @@ public void checkForHttps() { logger.warn("\n\n**\n** WARNING: Configured issuer url is not using https scheme.\n**\n\n"); } } + + if (languageNamespaces == null || languageNamespaces.isEmpty()) { + logger.error("No configured language namespaces! Text rendering will fail!"); + } } /** @@ -171,7 +181,21 @@ public void setLocale(Locale locale) { this.locale = locale; } - /** + /** + * @return the languageNamespaces + */ + public List getLanguageNamespaces() { + return languageNamespaces; + } + + /** + * @param languageNamespaces the languageNamespaces to set + */ + public void setLanguageNamespaces(List languageNamespaces) { + this.languageNamespaces = languageNamespaces; + } + + /** * @return true if dual client is configured, otherwise false */ public boolean isDualClient() { @@ -184,4 +208,19 @@ public boolean isDualClient() { public void setDualClient(boolean dualClient) { this.dualClient = dualClient; } + + /** + * Get the list of namespaces as a JSON string + * @return + */ + public String getLanguageNamespacesString() { + return new Gson().toJson(getLanguageNamespaces()); + } + + /** + * Get the default namespace (first in the nonempty list) + */ + public String getDefaultLanguageNamespace() { + return getLanguageNamespaces().get(0); + } } diff --git a/openid-connect-common/src/test/java/org/mitre/openid/connect/config/ConfigurationPropertiesBeanTest.java b/openid-connect-common/src/test/java/org/mitre/openid/connect/config/ConfigurationPropertiesBeanTest.java index 9ebeb8ca8c..2d0bbca481 100644 --- a/openid-connect-common/src/test/java/org/mitre/openid/connect/config/ConfigurationPropertiesBeanTest.java +++ b/openid-connect-common/src/test/java/org/mitre/openid/connect/config/ConfigurationPropertiesBeanTest.java @@ -63,7 +63,7 @@ public void testCheckForHttpsIssuerHttpDefaultFlag() { // leave as default, which is unset/false try { bean.setIssuer("http://localhost:8080/openid-connect-server/"); - bean.checkForHttps(); + bean.checkConfigConsistency(); } catch (BeanCreationException e) { fail("Unexpected BeanCreationException for http issuer with default forceHttps, message:" + e.getMessage()); } @@ -77,7 +77,7 @@ public void testCheckForHttpsIssuerHttpFalseFlag() { try { bean.setIssuer("http://localhost:8080/openid-connect-server/"); bean.setForceHttps(false); - bean.checkForHttps(); + bean.checkConfigConsistency(); } catch (BeanCreationException e) { fail("Unexpected BeanCreationException for http issuer with forceHttps=false, message:" + e.getMessage()); } @@ -90,7 +90,7 @@ public void testCheckForHttpsIssuerHttpTrueFlag() { // set to true bean.setIssuer("http://localhost:8080/openid-connect-server/"); bean.setForceHttps(true); - bean.checkForHttps(); + bean.checkConfigConsistency(); } @Test @@ -100,7 +100,7 @@ public void testCheckForHttpsIssuerHttpsDefaultFlag() { // leave as default, which is unset/false try { bean.setIssuer("https://localhost:8080/openid-connect-server/"); - bean.checkForHttps(); + bean.checkConfigConsistency(); } catch (BeanCreationException e) { fail("Unexpected BeanCreationException for https issuer with default forceHttps, message:" + e.getMessage()); } @@ -114,7 +114,7 @@ public void testCheckForHttpsIssuerHttpsFalseFlag() { try { bean.setIssuer("https://localhost:8080/openid-connect-server/"); bean.setForceHttps(false); - bean.checkForHttps(); + bean.checkConfigConsistency(); } catch (BeanCreationException e) { fail("Unexpected BeanCreationException for https issuer with forceHttps=false, message:" + e.getMessage()); } @@ -128,7 +128,7 @@ public void testCheckForHttpsIssuerHttpsTrueFlag() { try { bean.setIssuer("https://localhost:8080/openid-connect-server/"); bean.setForceHttps(true); - bean.checkForHttps(); + bean.checkConfigConsistency(); } catch (BeanCreationException e) { fail("Unexpected BeanCreationException for https issuer with forceHttps=true, message:" + e.getMessage()); } diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/server-config.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/server-config.xml index 91a0c67ca6..d4f5a7bb45 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/server-config.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/server-config.xml @@ -48,7 +48,18 @@ - + + + + diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/tags/header.tag b/openid-connect-server-webapp/src/main/webapp/WEB-INF/tags/header.tag index 76763d0513..3152917d45 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/tags/header.tag +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/tags/header.tag @@ -40,7 +40,12 @@ $.i18n.init({ fallbackLng: "en", lng: "${config.locale}", - resGetPath: "resources/js/locale/__lng__/messages.json" + resGetPath: "resources/js/locale/__lng__/__ns__.json", + ns: { + namespaces: ${config.languageNamespacesString}, + defaultNs: '${config.defaultLanguageNamespace}' + }, + fallbackNS: ${config.languageNamespacesString} }); moment.locale("${config.locale}"); // safely set the title of the application diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/config/JsonMessageSource.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/config/JsonMessageSource.java index ef000507f8..545df09f72 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/config/JsonMessageSource.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/config/JsonMessageSource.java @@ -21,13 +21,16 @@ import java.io.IOException; import java.io.InputStreamReader; import java.text.MessageFormat; +import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Locale; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.support.AbstractMessageSource; import org.springframework.core.io.Resource; @@ -50,19 +53,22 @@ public class JsonMessageSource extends AbstractMessageSource { private Locale fallbackLocale = new Locale("en"); // US English is the fallback language - private Map languageMaps = new HashMap<>(); - + private Map> languageMaps = new HashMap<>(); + + @Autowired + private ConfigurationPropertiesBean config; + @Override protected MessageFormat resolveCode(String code, Locale locale) { - JsonObject lang = getLanguageMap(locale); + List langs = getLanguageMap(locale); - String value = getValue(code, lang); + String value = getValue(code, langs); if (value == null) { // if we haven't found anything, try the default locale - lang = getLanguageMap(fallbackLocale); - value = getValue(code, lang); + langs = getLanguageMap(fallbackLocale); + value = getValue(code, langs); } if (value == null) { @@ -76,6 +82,31 @@ protected MessageFormat resolveCode(String code, Locale locale) { } /** + * Get a value from the set of maps, taking the first match in order + * @param code + * @param langs + * @return + */ + private String getValue(String code, List langs) { + if (langs == null || langs.isEmpty()) { + // no language maps, nothing to look up + return null; + } + + for (JsonObject lang : langs) { + String value = getValue(code, lang); + if (value != null) { + // short circuit out of here if we find a match, otherwise keep going through the list + return value; + } + } + + // if we didn't find anything return null + return null; + } + + /** + * Get a value from a single map * @param code * @param locale * @param lang @@ -126,20 +157,24 @@ private String getValue(String code, JsonObject lang) { * @param locale * @return */ - private JsonObject getLanguageMap(Locale locale) { + private List getLanguageMap(Locale locale) { if (!languageMaps.containsKey(locale)) { try { - String filename = locale.getLanguage() + File.separator + "messages.json"; - - Resource r = getBaseDirectory().createRelative(filename); - - logger.info("No locale loaded, trying to load from " + r); - - JsonParser parser = new JsonParser(); - JsonObject obj = (JsonObject) parser.parse(new InputStreamReader(r.getInputStream(), "UTF-8")); - - languageMaps.put(locale, obj); + List set = new ArrayList<>(); + for (String namespace : config.getLanguageNamespaces()) { + String filename = locale.getLanguage() + File.separator + namespace + ".json"; + + Resource r = getBaseDirectory().createRelative(filename); + + logger.info("No locale loaded, trying to load from " + r); + + JsonParser parser = new JsonParser(); + JsonObject obj = (JsonObject) parser.parse(new InputStreamReader(r.getInputStream(), "UTF-8")); + + set.add(obj); + } + languageMaps.put(locale, set); } catch (JsonIOException | JsonSyntaxException | IOException e) { logger.error("Unable to load locale", e); } From c59f722cc2b2cf951b94c9680f092ea318957f92 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 25 Nov 2015 15:36:15 -0500 Subject: [PATCH 133/465] enforce pairwise identifier consistency in UI, closes #969 --- .../src/main/webapp/resources/js/client.js | 27 ++++++++++++++++--- .../src/main/webapp/resources/js/dynreg.js | 25 ++++++++++++++--- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/client.js b/openid-connect-server-webapp/src/main/webapp/resources/js/client.js index 770c6fa647..842b28a270 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/client.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/client.js @@ -907,7 +907,26 @@ var ClientFormView = Backbone.View.extend({ refreshTokenValiditySeconds = this.getFormTokenNumberValue($('#refreshTokenValidityTime input[type=text]').val(), $('#refreshTokenValidityTime select').val()); } } - + + // make sure that the subject identifier is consistent with the redirect URIs + var subjectType = $('#subjectType input').filter(':checked').val(); + var redirectUris = this.redirectUrisCollection.pluck("item"); + var sectorIdentifierUri = $('#sectorIdentifierUri input').val(); + if (subjectType == 'PAIRWISE' && redirectUris.length > 1 && sectorIdentifierUri == '') { + //Display an alert with an error message + $('#modalAlert div.modal-header').html("Consistency error"); + $('#modalAlert div.modal-body').html("Pairwise identifiers cannot be used with multiple redirect URIs unless a sector identifier URI is also registered."); + + $("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog + "backdrop" : "static", + "keyboard" : true, + "show" : true // ensure the modal is shown immediately + }); + + return false; + + } + // process the JWKS var jwksUri = null; var jwks = null; @@ -947,7 +966,7 @@ var ClientFormView = Backbone.View.extend({ clientId:$('#clientId input').val(), clientSecret: clientSecret, generateClientSecret:generateClientSecret, - redirectUris: this.redirectUrisCollection.pluck("item"), + redirectUris: redirectUris, clientDescription:$('#clientDescription textarea').val(), logoUri:$('#logoUri input').val(), grantTypes: grantTypes, @@ -963,10 +982,10 @@ var ClientFormView = Backbone.View.extend({ applicationType: $('#applicationType input').filter(':checked').val(), jwksUri: jwksUri, jwks: jwks, - subjectType: $('#subjectType input').filter(':checked').val(), + subjectType: subjectType, tokenEndpointAuthMethod: tokenEndpointAuthMethod, responseTypes: responseTypes, - sectorIdentifierUri: $('#sectorIdentifierUri input').val(), + sectorIdentifierUri: sectorIdentifierUri, initiateLoginUri: $('#initiateLoginUri input').val(), postLogoutRedirectUris: this.postLogoutRedirectUrisCollection.pluck('item'), reuseRefreshToken: $('#reuseRefreshToken').is(':checked'), diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/dynreg.js b/openid-connect-server-webapp/src/main/webapp/resources/js/dynreg.js index 10aa99dd79..49b02acf30 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/dynreg.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/dynreg.js @@ -388,6 +388,25 @@ var DynRegEditView = Backbone.View.extend({ } } + // make sure that the subject identifier is consistent with the redirect URIs + var subjectType = $('#subjectType input').filter(':checked').val(); + var redirectUris = this.redirectUrisCollection.pluck("item"); + var sectorIdentifierUri = $('#sectorIdentifierUri input').val(); + if (subjectType == 'PAIRWISE' && redirectUris.length > 1 && sectorIdentifierUri == '') { + //Display an alert with an error message + $('#modalAlert div.modal-header').html("Consistency error"); + $('#modalAlert div.modal-body').html("Pairwise identifiers cannot be used with multiple redirect URIs unless a sector identifier URI is also registered."); + + $("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog + "backdrop" : "static", + "keyboard" : true, + "show" : true // ensure the modal is shown immediately + }); + + return false; + + } + // process the JWKS var jwksUri = null; var jwks = null; @@ -422,7 +441,7 @@ var DynRegEditView = Backbone.View.extend({ var attrs = { client_name:$('#clientName input').val(), - redirect_uris: this.redirectUrisCollection.pluck("item"), + redirect_uris: redirectUris, logo_uri:$('#logoUri input').val(), grant_types: grantTypes, scope: scopes, @@ -433,10 +452,10 @@ var DynRegEditView = Backbone.View.extend({ application_type: $('#applicationType input').filter(':checked').val(), jwks_uri: jwksUri, jwks: jwks, - subject_type: $('#subjectType input').filter(':checked').val(), + subject_type: subjectType, token_endpoint_auth_method: $('#tokenEndpointAuthMethod input').filter(':checked').val(), response_types: responseTypes, - sector_identifier_uri: $('#sectorIdentifierUri input').val(), + sector_identifier_uri: sectorIdentifierUri, initiate_login_uri: $('#initiateLoginUri input').val(), post_logout_redirect_uris: this.postLogoutRedirectUrisCollection.pluck('item'), require_auth_time: $('#requireAuthTime input').is(':checked'), From fcfc620d51488b56effc9cec437e02629eb73b44 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 25 Nov 2015 15:36:31 -0500 Subject: [PATCH 134/465] updated client API with more useful errors, removed unused service reference --- .../main/java/org/mitre/openid/connect/web/ClientAPI.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java index 0b9e096b1f..38f18e2c0a 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java @@ -24,7 +24,6 @@ import org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod; import org.mitre.oauth2.service.ClientDetailsEntityService; import org.mitre.oauth2.web.AuthenticationUtilities; -import org.mitre.openid.connect.service.UserInfoService; import org.mitre.openid.connect.view.ClientEntityViewForAdmins; import org.mitre.openid.connect.view.ClientEntityViewForUsers; import org.mitre.openid.connect.view.HttpCodeView; @@ -75,9 +74,6 @@ public class ClientAPI { @Autowired private ClientDetailsEntityService clientService; - @Autowired - private UserInfoService userInfoService; - private JsonParser parser = new JsonParser(); private Gson gson = new GsonBuilder() @@ -239,7 +235,7 @@ public String apiAddClient(@RequestBody String jsonString, Model m, Authenticati } catch (IllegalArgumentException e) { logger.error("Unable to save client: {}", e.getMessage()); m.addAttribute(HttpCodeView.CODE, HttpStatus.BAD_REQUEST); - m.addAttribute(JsonErrorView.ERROR_MESSAGE, "Unable to save client"); + m.addAttribute(JsonErrorView.ERROR_MESSAGE, "Unable to save client: " + e.getMessage()); return JsonErrorView.VIEWNAME; } } @@ -340,7 +336,7 @@ public String apiUpdateClient(@PathVariable("id") Long id, @RequestBody String j } catch (IllegalArgumentException e) { logger.error("Unable to save client: {}", e.getMessage()); m.addAttribute(HttpCodeView.CODE, HttpStatus.BAD_REQUEST); - m.addAttribute(JsonErrorView.ERROR_MESSAGE, "Unable to save client"); + m.addAttribute(JsonErrorView.ERROR_MESSAGE, "Unable to save client: " + e.getMessage()); return JsonErrorView.VIEWNAME; } } From 1ed3e2c47a3644d4c16cca64bc23b616df151df1 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 25 Nov 2015 15:44:11 -0500 Subject: [PATCH 135/465] quieted logging on database cleanup tasks when no expired elements are found --- .../DefaultOAuth2AuthorizationCodeService.java | 5 +++-- .../impl/DefaultOAuth2ProviderTokenService.java | 14 ++++++++++---- .../service/impl/DefaultApprovedSiteService.java | 4 +++- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2AuthorizationCodeService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2AuthorizationCodeService.java index 8403a6f5b5..02062090dc 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2AuthorizationCodeService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2AuthorizationCodeService.java @@ -121,8 +121,9 @@ public void clearExpiredAuthorizationCodes() { repository.remove(code); } - logger.info("Removed " + codes.size() + " expired authorization codes."); - + if (codes.size() > 0) { + logger.info("Removed " + codes.size() + " expired authorization codes."); + } } /** diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java index f71b445743..a66eff5d83 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java @@ -423,14 +423,16 @@ public List getRefreshTokensForClient(ClientDetailsEnt */ @Override public void clearExpiredTokens() { - logger.info("Cleaning out all expired tokens"); + logger.debug("Cleaning out all expired tokens"); // get all the duplicated tokens first to maintain consistency tokenRepository.clearDuplicateAccessTokens(); tokenRepository.clearDuplicateRefreshTokens(); Collection accessTokens = getExpiredAccessTokens(); - logger.info("Found " + accessTokens.size() + " expired access tokens"); + if (accessTokens.size() > 0) { + logger.info("Found " + accessTokens.size() + " expired access tokens"); + } for (OAuth2AccessTokenEntity oAuth2AccessTokenEntity : accessTokens) { try { revokeAccessToken(oAuth2AccessTokenEntity); @@ -442,13 +444,17 @@ public void clearExpiredTokens() { } Collection refreshTokens = getExpiredRefreshTokens(); - logger.info("Found " + refreshTokens.size() + " expired refresh tokens"); + if (refreshTokens.size() > 0) { + logger.info("Found " + refreshTokens.size() + " expired refresh tokens"); + } for (OAuth2RefreshTokenEntity oAuth2RefreshTokenEntity : refreshTokens) { revokeRefreshToken(oAuth2RefreshTokenEntity); } Collection authHolders = getOrphanedAuthenticationHolders(); - logger.info("Found " + authHolders.size() + " orphaned authentication holders"); + if (authHolders.size() > 0) { + logger.info("Found " + authHolders.size() + " orphaned authentication holders"); + } for(AuthenticationHolderEntity authHolder : authHolders) { authenticationHolderRepository.remove(authHolder); } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultApprovedSiteService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultApprovedSiteService.java index 15145c05fa..d61f7f6616 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultApprovedSiteService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultApprovedSiteService.java @@ -158,7 +158,9 @@ public void clearExpiredSites() { logger.info("Clearing expired approved sites"); Collection expiredSites = getExpired(); - logger.info("Found " + expiredSites.size() + " expired approved sites."); + if (expiredSites.size() > 0) { + logger.info("Found " + expiredSites.size() + " expired approved sites."); + } if (expiredSites != null) { for (ApprovedSite expired : expiredSites) { remove(expired); From 9ffe877766d6603c7b3c2e3cb19e84d0a77ed0cb Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 25 Nov 2015 16:06:17 -0500 Subject: [PATCH 136/465] added getId to address interface, closes #958 --- .../main/java/org/mitre/openid/connect/model/Address.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/Address.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/Address.java index b99cabb668..a644a02465 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/Address.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/Address.java @@ -20,6 +20,12 @@ public interface Address extends Serializable { + /** + * Get the system-specific ID of the Address object + * @return + */ + public Long getId(); + /** * @return the formatted address */ From ea77bf2a1907861cb73c425298e8bc1545b7f652 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 2 Dec 2015 16:51:55 -0500 Subject: [PATCH 137/465] quieted approved site cleanup --- .../openid/connect/service/impl/DefaultApprovedSiteService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultApprovedSiteService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultApprovedSiteService.java index d61f7f6616..27625f2f5e 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultApprovedSiteService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultApprovedSiteService.java @@ -155,7 +155,7 @@ public void clearApprovedSitesForClient(ClientDetails client) { @Override public void clearExpiredSites() { - logger.info("Clearing expired approved sites"); + logger.debug("Clearing expired approved sites"); Collection expiredSites = getExpired(); if (expiredSites.size() > 0) { From 1596b6b9e79858111a61fceedbeb90b6044f5d9f Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Thu, 10 Dec 2015 16:22:22 -0500 Subject: [PATCH 138/465] Updated UMA server to use new multi-part messages structure --- .../webapp/WEB-INF/application-context.xml | 1 + .../src/main/webapp/WEB-INF/server-config.xml | 7 + .../resources/js/locale/en/messages.json | 494 ------------------ .../webapp/resources/js/locale/en/uma.json | 50 ++ 4 files changed, 58 insertions(+), 494 deletions(-) delete mode 100644 uma-server-webapp/src/main/webapp/resources/js/locale/en/messages.json create mode 100644 uma-server-webapp/src/main/webapp/resources/js/locale/en/uma.json diff --git a/uma-server-webapp/src/main/webapp/WEB-INF/application-context.xml b/uma-server-webapp/src/main/webapp/WEB-INF/application-context.xml index 8e5a73405b..c80b2bd92f 100644 --- a/uma-server-webapp/src/main/webapp/WEB-INF/application-context.xml +++ b/uma-server-webapp/src/main/webapp/WEB-INF/application-context.xml @@ -218,6 +218,7 @@ + diff --git a/uma-server-webapp/src/main/webapp/WEB-INF/server-config.xml b/uma-server-webapp/src/main/webapp/WEB-INF/server-config.xml index added56d98..b6d6a94f81 100644 --- a/uma-server-webapp/src/main/webapp/WEB-INF/server-config.xml +++ b/uma-server-webapp/src/main/webapp/WEB-INF/server-config.xml @@ -49,6 +49,13 @@ + + + + uma + messages + + diff --git a/uma-server-webapp/src/main/webapp/resources/js/locale/en/messages.json b/uma-server-webapp/src/main/webapp/resources/js/locale/en/messages.json deleted file mode 100644 index c9e7d31c0b..0000000000 --- a/uma-server-webapp/src/main/webapp/resources/js/locale/en/messages.json +++ /dev/null @@ -1,494 +0,0 @@ -{ - "admin": { - "blacklist": "Blacklist", - "blacklist-form": { - "blacklisted-uris": "Blacklisted URIs" - }, - "home": "Home", - "list-widget": { - "empty": "There are no items in this list.", - "tooltip": "Click to display full value." - }, - "manage-blacklist": "Manage Blacklisted Clients", - "self-service-client": "Self-service Client Registration", - "self-service-resource": "Self-service Protected Resource Registration", - "user-profile": { - "claim": "Claim name:", - "show": "View User Profile", - "text": "Your user profile has the following information:", - "value": "Claim value:" - }, - "policies": "Manage Protected Resource Policies" - }, - "client": { - "client-form": { - "access": "Access", - "access-token-no-timeout": "Access tokens do not time out", - "access-token-timeout": "Access Token Timeout", - "access-token-timeout-help": "Enter this time in seconds, minutes, or hours.", - "acr-values": "Default ACR Values", - "acr-values-placeholder": "new ACR value", - "acr-values-help": "Default Authentication Context Reference to request for this client", - "allow-introspection": "Allow calls to the Introspection Endpoint?", - "authentication-method": "Token Endpoint Authentication Method", - "authorization-code": "authorization code", - "client-credentials": "client credentials", - "client-description": "Description", - "client-description-help": "Human-readable text description", - "client-description-placeholder": "Type a description", - "client-id": "Client ID", - "client-id-help": "Unique identifier. If you leave this blank it will be automatically generated.", - "client-id-placeholder": "Type something", - "client-name": "Client name", - "client-name-help": "Human-readable application name", - "client-name-placeholder": "Type something", - "client-secret": "Client Secret", - "client-secret-placeholder": "Type a secret", - "contacts": "Contacts", - "contacts-help": "List of contacts for administrators of this client.", - "contacts-placeholder": "new contact", - "credentials": "Credentials", - "crypto": { - "a128cbc-hs256": "Composite Authenticated Encryption algorithm using AES in Cipher Block Chaining (CBC) mode with PKCS #5 padding with an integrity calculation using HMAC SHA-256, using a 256 bit CMK (and 128 bit CEK)", - "a256cbc-hs512": "Composite Authenticated Encryption algorithm using AES in CBC mode with PKCS #5 padding with an integrity calculation using HMAC SHA-512, using a 512 bit CMK (and 256 bit CEK)", - "a128gcm": "AES GCM using 128 bit keys", - "a256gcm": "AES GCM using 256 bit keys", - "a128kw": "AES Key Wrap Algorithm using 128 bit keys", - "a256kw": "AES Key Wrap Algorithm using 256 bit keys", - "default": "Use server default", - "dir": "Direct use of a shared symmetric key as the Content Master Key (CMK) for the block encryption step", - "ecdh-es": "Elliptic Curve Diffie-Hellman Ephemeral Static key agreement using the Concat KDF, with the agreed-upon key being used directly as the Content Master Key", - "ecdh-es-a128kw": "Elliptic Curve Diffie-Hellman Ephemeral Static key agreement per ECDH-ES and Section 4.7, but where the agreed-upon key is used to wrap the Content Master Key (CMK) with the A128KW function", - "ecdh-es-a256kw": "Elliptic Curve Diffie-Hellman Ephemeral Static key agreement per ECDH-ES and Section 4.7, but where the agreed-upon key is used to wrap the Content Master Key (CMK) with the A256KW function", - "none": "No encryption", - "rsa-oaep": "RSAES using Optimal Asymmetric Encryption Padding (OAEP)", - "rsa1-5": "RSAES-PKCS1-V1_5" - }, - "cryptography": "Crypto", - "display-secret": "Display/edit client secret:", - "edit": "Edit Client", - "generate-new-secret": "Generate a new client secret?", - "generate-new-secret-help": "New secret will be generated when you click 'Save'", - "generate-on-save": "Generate on Save", - "grant-types": "Grant Types", - "home": "Home Page", - "home-help": "URL for the client's home page, will be displayed to the user", - "hours": "hours", - "id": "ID:", - "id-token-crypto-algorithm": "ID Token Encryption Algorithm", - "id-token-crypto-method": "ID Token Encryption Method", - "id-token-signing-algorithm": "ID Token Signing Algorithm", - "id-token-timeout": "ID Token Timeout", - "implicit": "implicit", - "initiate-login": "Initiate Login", - "initiate-login-help": "URL to initiate login on the client", - "introspection": "Introspection", - "jwk-set": "JWK Set", - "jwk-set-help": "URL for the client's JSON Web Key set", - "logo": "Logo", - "logo-help": "URL that points to a logo image, will be displayed on approval page", - "main": "Main", - "max-age": "Default Max Age", - "max-age-help": "Default maximum session age before re-prompting", - "minutes": "minutes", - "new": "New Client", - "other": "Other", - "pairwise": "Pairwise", - "password": "password", - "policy": "Policy Statement", - "policy-help": "URL for the Policy Statement of this client, will be displayed to the user", - "post-logout": "Post-Logout Redirect", - "post-logout-help": "URL to redirect the client to after a logout operation", - "public": "Public", - "redelegation": "redelegation", - "redirect-uris": "Redirect URI(s)", - "redirect-uris-help": "URIs that the client can be redirected to after the authorization page", - "refresh": "refresh", - "refresh-tokens": "Refresh Tokens", - "refresh-tokens-issued": "Refresh tokens are issued for this client", - "refresh-tokens-reused": "Refresh tokens for this client are re-used", - "refresh-tokens-no-expire": "Refresh tokens do not time out", - "registered": "Registered at", - "registration-token": "Registration Token:", - "registration-access-token": "Registration Access Token", - "registration-token-error": "There was a problem loading the registration access token for this client.", - "request-object-signing-algorithm": "Request Object Signing Algorithm", - "request-uri": "Request URIs", - "request-uri-help": "URIs containing request objects used by this client", - "require-auth-time": "Require Authentication Time", - "require-auth-time-label": "Always require that the auth_time claim be sent in the id token", - "response-types": "Response Types", - "rotate-registration-token": "Rotate registration token", - "rotate-registration-token-confirm": "Are you sure you want to rotate this client's registration token?", - "rotate-registration-token-error": "There was a problem rotating the registration access token for this client.", - "saved": { - "no-secret": "No client secret", - "saved": "Client Saved", - "secret": "Secret:", - "show-secret": "Show Secret", - "unchanged": "unchanged" - }, - "scope-placeholder": "new scope", - "scope-help": "OAuth scopes this client is allowed to request", - "seconds": "seconds", - "secret-asymmetric-jwt": "Asymmetrically-signed JWT assertion", - "secret-http": "Client Secret over HTTP Basic", - "secret-none": "No authentication", - "secret-post": "Client Secret over HTTP POST", - "secret-symmetric-jwt": "Client Secret via symmetrically-signed JWT assertion", - "sector-identifier": "Sector Identifier URI", - "signing": { - "any": "Any allowed", - "default": "Use server default", - "ecdsa-256": "ECDSA using P-256 curve and SHA-256 hash algorithm", - "ecdsa-384": "ECDSA using P-384 curve and SHA-384 hash algorithm", - "ecdsa-512": "ECDSA using P-512 curve and SHA-512 hash algorithm", - "hmac-256": "HMAC using SHA-256 hash algorithm", - "hmac-384": "HMAC using SHA-384 hash algorithm", - "hmac-512": "HMAC using SHA-512 hash algorithm", - "none": "No digital signature", - "rsassa-256": "RSASSA using SHA-256 hash algorithm", - "rsassa-384": "RSASSA using SHA-384 hash algorithm", - "rsassa-512": "RSASSA using SHA-512 hash algorithm" - }, - "subject-type": "Subject Type", - "terms": "Terms of Service", - "terms-help": "URL for the Terms of Service of this client, will be displayed to the user", - "token-signing-algorithm": "Token Endpoint Authentication Signing Algorithm", - "tokens": "Tokens", - "type": "Application Type", - "type-native": "Native", - "type-web": "Web", - "unknown": "(Unknown)", - "user-info-crypto-algorithm": "User Info Endpoint Encryption Algorithm", - "user-info-crypto-method": "User Info Endpoint Encryption Method", - "user-info-signing-algorithm": "User Info Endpoint Signing Algorithm" - }, - "client-table": { - "allow-introspection-tooltip": "This client can perform token introspection", - "confirm": "Are you sure sure you would like to delete this client?", - "dynamically-registered-tooltip": "This client was dynamically registered. Click to view registration access token", - "match": { - "contacts": "contacts", - "description": "description", - "homepage": "home page", - "id": "id", - "logo": "logo", - "name": "name", - "policy": "policy", - "redirect": "redirect uri", - "scope": "scope", - "terms": "terms of service" - }, - "matched-search": "Matched search:", - "new": "New Client", - "no-clients": "There are no registered clients on this server.", - "no-matches": "There are no clients that match your search criteria.", - "no-redirect": "NO REDIRECT URI", - "registered": "Registrered", - "search": "Search...", - "whitelist": "Whitelist", - "unknown": "at an unknown time" - }, - "manage": "Manage Clients", - "more-info": { - "contacts": "Administrative Contacts:", - "home": "Home Page:", - "more": "more information", - "policy": "Policy:", - "terms": "Terms of Service:" - }, - "newClient": "New Client" - }, - "common": { - "cancel": "Cancel", - "client": "Client", - "clients": "Clients", - "close": "Close", - "delete": "Delete", - "description": "Description", - "dynamically-registered": "This client was dynamically registered", - "edit": "Edit", - "expires": "Expires:", - "information": "Information", - "new": "New", - "not-yet-implemented": "Not Yet Implemented", - "not-yet-implemented-content": "The value of this field will be saved with the client, but the server does not currently process anything with it. Future versions of the server library will make use of this.", - "revoke": "Revoke", - "save": "Save", - "scopes": "Scopes", - "statistics": "Statistics" - }, - "dynreg": { - "client-id-placeholder": "Enter Client ID", - "configuration-url": "Client Configuration URL", - "edit-dynamically-registered": "Edit a Dynamically Registered Client", - "edit-existing": "Edit an existing client", - "edit-existing-help": "Paste in your client ID and registration access token to access the client.", - "invalid-access-token": "Invalid client or registration access token.", - "new-client": "Register a new client", - "or": " - OR - ", - "regtoken-placeholder": "Enter Registration Access Token", - "warning": "Warning! You MUST protect your Client ID, Client Secret (if provided), and your Registration Access Token. If you lose your Client ID or Registration Access Token, you will no longer have access to your client's registration records and you will need to register a new client.", - "will-be-generated": "Will be generated" - }, - "grant": { - "manage-approved-sites": "Manage Approved Sites", - "refresh": "Refresh", - "grant-table": { - "active-tokens": "Number of currently active access tokens", - "application": "Application", - "approved-sites": "Approved Sites", - "authorized": "Authorized:", - "dynamically-registered": "This client was dynamically registered", - "expires": "Expires:", - "last-accessed": "Last accessed:", - "never": "Never", - "no-sites": "You have not approved any sites.", - "no-whitelisted": "You have not accessed any whitelisted sites.", - "pre-approved": "These are sites that have been pre-approved by an administrator.", - "text": "These are sites you have approved manually. If the same site asks for the same access in the future, it will be granted without prompting.", - "unknown": "Unknown", - "whitelist-note": "NOTE: If you revoke them here, they will automatically be re-approved on your next visit wthout prompting.", - "whitelisted-site": "This site was whitelisted by an adminstrator", - "whitelisted-sites": "Whitelisted Sites" - } - }, - "rsreg": { - "resource-id-placeholder": "Enter Resource ID", - "configuration-url": "Client Configuration URL", - "edit": "Edit Protected Resource", - "edit-existing": "Edit an existing protected resource", - "edit-existing-help": "Paste in your ID and registration access token to access the resource's properties.", - "invalid-access-token": "Invalid client or registration access token.", - "new": "New Protected Resource", - "new-resource": "Register a new protected resource", - "or": " - OR - ", - "regtoken-placeholder": "Enter Registration Access Token", - "will-be-generated": "Will be generated", - "warning": "Warning! You MUST protect your Client ID, Client Secret (if provided), and your Registration Access Token. If you lose your Client ID or Registration Access Token, you will no longer have access to your client's registration records and you will need to register a new client.", - "client-form": { - "scope-help": "Scopes that this resource will be able to introspect tokens for." - } - }, - "scope": { - "manage": "Manage System Scopes", - "scope-list": { - "no-scopes": "NO SCOPES" - }, - "system-scope-form": { - "default": "default scope", - "default-help": "Newly-created clients get this scope by default?", - "description-help": "Human-readable text description", - "description-placeholder": "Type a description", - "restricted": "restricted", - "restricted-help": "Restricted scopes are only usable by system administrators and are unavailable to dynamically registered clients and protected resources", - "edit": "Edit Scope", - "icon": "Icon", - "new": "New Scope", - "select-icon": "Select an icon", - "structured": "is a structured scope", - "structured-help": "Is the scope structured with structured values like base:extension?", - "structured-param-help": "Human-readable description of the structured parameter", - "subject-type": "Subject Type", - "value": "Scope value", - "value-help": "Single string with no spaces", - "value-placeholder": "scope" - }, - "system-scope-table": { - "confirm": "Are you sure sure you would like to delete this scope? Clients that have this scope will still be able to ask for it.", - "new": "New Scope", - "text": "There are no system scopes defined. Clients may still have custom scopes.", - "tooltip-restricted": "This scope can be used only by adminisrtators. It is not available for dynamic registration.", - "tooltip-default": "This scope is automatically assigned to newly registered clients." - } - }, - "token": { - "manage": "Manage Active Tokens", - "token-table": { - "access-tokens": "Access Tokens", - "associated-id": "This access token was issued with an associated ID token.", - "associated-refresh": "This access token was issued with an associated refresh token.", - "click-to-display": "Click to display full token value", - "confirm": "Are you sure sure you would like to revoke this token?", - "confirm-refresh": "Are you sure sure you would like to revoke this refresh token and its associated access tokens?", - "expires": "Expires", - "no-access": "There are no active access tokens.", - "no-refresh": "There are no active refresh tokens.", - "number-of-tokens": "Number of associated access tokens", - "refresh-tokens": "Refresh Tokens", - "text": "Access tokens are usually short-lived and provide clients with access to specific resources. ID Tokens are specialized access tokens to facilitate log on using OpenID Connect.", - "text-refresh": "Refresh tokens are usually long-lived and provide clients with the ability to get new access tokens without end-user involvement.", - "token-info": "Token Information" - } - }, - "whitelist": { - "confirm": "Are you sure you want to delete this whitelist entry?", - "edit": "Edit Whitelist", - "manage": "Manage Whitelisted Sites", - "new": "New Whitelist", - "whitelist": "Whitelist", - "whitelist-form": { - "allowed-scopes": "Allowed Scopes", - "edit": "Edit Whitelisted Site", - "new": "New Whitelisted Site", - "scope-help": "List of scopes that will be automatically approved when this client makes a request", - "scope-placeholder": "new scope" - }, - "whitelist-table": { - "no-sites": "There are no whitelisted sites. Use the whitelist button on the client management page to create one." - } - }, - "policy" : { - "resource-sets": "Resource Sets", - "edit-policies": "Edit Policies", - "new-policy": "New Policy", - "edit-policy": "Edit Policy", - "loading-policies": "Policies", - "loading-policy": "Policy", - "loading-rs": "Resource Set", - "rs-table": { - "confirm": "Are you sure you want to delete this resource set?", - "no-resource-sets": "There are no resource sets registered. Introduce a protected to this authorization server to let it register some.", - "scopes": "Scopes", - "shared-with": "Shared with:", - "shared-nobody": "NOBODY", - "shared-nobody-tooltip": "This resource is not accessible by anyone else, edit the policies and share it with someone.", - "sharing": "Sharing Policies" - }, - "policy-table": { - "new": "Add New Policy", - "return": "Return to list", - "edit": "Edit Policy", - "confirm": "Are you sure you want to delete this policy?", - "delete": "Delete", - "no-policies": "There are no policies for this resource set: This resource set is inaccessible by others.", - "required-claims": "Required Claims", - "required-claims-info": "Users that you share this resource will with need to be able to present the following claims in order to access the resource.", - "remove": "Remove", - "issuers": "Issuers", - "claim": "Claim", - "value": "Value" - }, - "policy-form": { - "email-address": "email address", - "share-email": "Share with email address", - "new": "New Policy", - "edit": "Edit Policy" - }, - "webfinger-error": "Error", - "webfinger-error-description": "The server was unable to find an identity provider for __email__." - }, - "copyright": "Powered by MITREid Connect {0} © 2015 The MITRE Corporation and MIT KIT..", - "about": { - "title": "About", - "body": "\nThis OpenID Connect service is built from the MITREid Connect Open Source project, from \nThe MITRE Corporation and the MIT Kerberos and Internet Trust Consortium.\n

\n

\nMore information about the project can be found at \nMITREid Connect on GitHub. \nThere, you can submit bug reports, give feedback, or even contribute code patches for additional features you'd like to see." - }, - "statistics": { - "title": "Statistics", - "number_users": "Number of users: {0}", - "number_clients": "Authorized clients: {0}", - "number_approvals": "Approved sites: {0}" - }, - "home": { - "title": "Home", - "welcome": { - "title": "Welcome!", - "body": "\nOpenID Connect is an internet-scale federated identity protocol built on top of the OAuth2 authorization framework. \nOpenID Connect lets you log into a remote site using your identity without exposing your credentials, like a username and password.

\n

Learn more »" - }, - "more": "More", - "about": { - "title": "About", - "body": "This OpenID Connect service is built from the MITREid Connect Open Source project, from \nThe MITRE Corporation and the MIT Kerberos and Internet Trust Consortium." - }, - "contact": { - "title": "Contact", - "body": "\nFor more information or support, contact the administrators of this system.

\n

Email »" - }, - "statistics": { - "title": "Current Statistics", - "loading": "Loading...", - "number_users": "Number of users: {0}", - "number_clients": "Authorized clients: {0}", - "number_approvals": "Approved sites: {0}" - } - }, - "contact": { - "title": "Contact", - "body": "To report bugs with the MITREid Connect software itself, use the \nGitHub issue tracker. \nFor problems relating to this server, contact the server's administrator." - }, - "topbar": { - "about": "About", - "contact": "Contact", - "statistics": "Statistics", - "home": "Home", - "login": "Log in", - "logout": "Log out" - }, - "sidebar": { - "administrative": { - "title": "Administrative", - "manage_clients": "Manage Clients", - "whitelisted_clients": "Whitelisted Clients", - "blacklisted_clients": "Blacklisted Clients", - "system_scopes": "System Scopes" - }, - "personal": { - "title": "Personal", - "approved_sites": "Manage Approved Sites", - "active_tokens": "Manage Active Tokens", - "profile_information": "View Profile Information", - "resource_policies": "Manage Protected Resource Policies" - }, - "developer": { - "title": "Developer", - "client_registration": "Self-service client registration", - "resource_registration": "Self-service protected resource registration" - } - }, - "manage": { - "ok": "OK", - "loading": "Loading", - "title": "Management Console" - }, - "approve": { - "dynamically-registered-unknown": "at an unknown time", - "title": "Approve Access", - "error": { - "not_granted": "Access could not be granted." - }, - "required_for": "Approval Required for", - "dynamically_registered": "This client was dynamically registered {0}.", - "caution": { - "title": "Caution", - "message": { - "none": "It has never been approved previously.", - "singular": "It has been approved {0} time previously.", - "plural": "It has been approved {0} times previously." - } - }, - "more_information": "more information", - "home_page": "Home page", - "policy": "Policy", - "terms": "Terms of Service", - "contacts": "Administrative Contacts", - "warning": "Warning", - "no_redirect_uri": "This client does not have any redirect URIs registered and someone could be using a malicious URI here.", - "redirect_uri": "You will be redirected to the following page if you click Approve: {0}", - "pairwise": "This client uses a pairwise identifier, which makes it more difficult to correlate your identity between sites.", - "no_scopes": "This client does not have any scopes registered and is therefore allowed to request any scopes available on the system. Proceed with caution.", - "access_to": "Access to", - "remember": { - "title": "Remember this decision", - "until_revoke": "remember this decision until I revoke it", - "one_hour": "remember this decision for one hour", - "next_time": "prompt me again next time" - }, - "do_authorize": "Do you authorize", - "label": { - "authorize": "Authorize", - "deny": "Deny" - } - } - -} \ No newline at end of file diff --git a/uma-server-webapp/src/main/webapp/resources/js/locale/en/uma.json b/uma-server-webapp/src/main/webapp/resources/js/locale/en/uma.json new file mode 100644 index 0000000000..246799ab3a --- /dev/null +++ b/uma-server-webapp/src/main/webapp/resources/js/locale/en/uma.json @@ -0,0 +1,50 @@ +{ + "admin": { + "policies": "Manage Protected Resource Policies" + }, + "policy" : { + "resource-sets": "Resource Sets", + "edit-policies": "Edit Policies", + "new-policy": "New Policy", + "edit-policy": "Edit Policy", + "loading-policies": "Policies", + "loading-policy": "Policy", + "loading-rs": "Resource Set", + "rs-table": { + "confirm": "Are you sure you want to delete this resource set?", + "no-resource-sets": "There are no resource sets registered. Introduce a protected to this authorization server to let it register some.", + "scopes": "Scopes", + "shared-with": "Shared with:", + "shared-nobody": "NOBODY", + "shared-nobody-tooltip": "This resource is not accessible by anyone else, edit the policies and share it with someone.", + "sharing": "Sharing Policies" + }, + "policy-table": { + "new": "Add New Policy", + "return": "Return to list", + "edit": "Edit Policy", + "confirm": "Are you sure you want to delete this policy?", + "delete": "Delete", + "no-policies": "There are no policies for this resource set: This resource set is inaccessible by others.", + "required-claims": "Required Claims", + "required-claims-info": "Users that you share this resource will with need to be able to present the following claims in order to access the resource.", + "remove": "Remove", + "issuers": "Issuers", + "claim": "Claim", + "value": "Value" + }, + "policy-form": { + "email-address": "email address", + "share-email": "Share with email address", + "new": "New Policy", + "edit": "Edit Policy" + }, + "webfinger-error": "Error", + "webfinger-error-description": "The server was unable to find an identity provider for __email__." + }, + "sidebar": { + "personal": { + "resource_policies": "Manage Protected Resource Policies" + } + } +} \ No newline at end of file From d120e8fb207675c6cfeaeb0f3af871280d4c4384 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Thu, 10 Dec 2015 16:23:15 -0500 Subject: [PATCH 139/465] return ID of resource set in Location URL by calling the right object --- .../java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java index 2f9799d07c..b68776a4b0 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java @@ -122,7 +122,7 @@ public String createResourceSet(@RequestBody String jsonString, Model m, Authent m.addAttribute(HttpCodeView.CODE, HttpStatus.CREATED); m.addAttribute(JsonEntityView.ENTITY, saved); - m.addAttribute(ResourceSetEntityAbbreviatedView.LOCATION, config.getIssuer() + URL + "/" + rs.getId()); + m.addAttribute(ResourceSetEntityAbbreviatedView.LOCATION, config.getIssuer() + URL + "/" + saved.getId()); return ResourceSetEntityAbbreviatedView.VIEWNAME; From be9d8948ef204f79450e13c43da1b492ce97bdea Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Thu, 10 Dec 2015 16:24:21 -0500 Subject: [PATCH 140/465] added UMA classes to logger configuration --- openid-connect-server-webapp/src/main/resources/log4j.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openid-connect-server-webapp/src/main/resources/log4j.xml b/openid-connect-server-webapp/src/main/resources/log4j.xml index 1f07862fb1..f8289edc91 100644 --- a/openid-connect-server-webapp/src/main/resources/log4j.xml +++ b/openid-connect-server-webapp/src/main/resources/log4j.xml @@ -45,6 +45,9 @@ + + + From 7f464c496b5a91dd8c20b046650407dee4621f6e Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 16 Dec 2015 14:51:12 -0500 Subject: [PATCH 141/465] changed copyright to new consortium name --- README.md | 2 +- checkstyle.xml | 30 +++++++++---------- openid-connect-client/pom.xml | 30 +++++++++---------- .../IntrospectingTokenService.java | 2 +- .../OAuth2AccessTokenImpl.java | 2 +- .../IntrospectionAuthorityGranter.java | 2 +- .../IntrospectionConfigurationService.java | 2 +- ...singIntrospectionConfigurationService.java | 2 +- ...eBasedIntrospectionAuthoritiesGranter.java | 2 +- .../SimpleIntrospectionAuthorityGranter.java | 2 +- ...aticIntrospectionConfigurationService.java | 2 +- .../client/NamedAdminAuthoritiesMapper.java | 2 +- .../client/OIDCAuthenticationFilter.java | 2 +- .../client/OIDCAuthenticationProvider.java | 2 +- .../connect/client/OIDCAuthoritiesMapper.java | 2 +- .../StaticPrefixTargetLinkURIChecker.java | 2 +- .../client/SubjectIssuerGrantedAuthority.java | 2 +- .../connect/client/TargetLinkURIChecker.java | 2 +- .../connect/client/UserInfoFetcher.java | 2 +- .../keypublisher/ClientKeyPublisher.java | 2 +- .../ClientKeyPublisherMapping.java | 2 +- .../client/keypublisher/JwkViewResolver.java | 2 +- .../client/model/IssuerServiceResponse.java | 2 +- .../service/AuthRequestOptionsService.java | 2 +- .../client/service/AuthRequestUrlBuilder.java | 2 +- .../service/ClientConfigurationService.java | 2 +- .../connect/client/service/IssuerService.java | 2 +- .../service/RegisteredClientService.java | 2 +- .../service/ServerConfigurationService.java | 2 +- ...egistrationClientConfigurationService.java | 2 +- .../DynamicServerConfigurationService.java | 2 +- .../impl/EncryptedAuthRequestUrlBuilder.java | 2 +- .../HybridClientConfigurationService.java | 2 +- .../service/impl/HybridIssuerService.java | 2 +- .../HybridServerConfigurationService.java | 2 +- .../impl/InMemoryRegisteredClientService.java | 2 +- .../impl/JsonFileRegisteredClientService.java | 2 +- .../impl/PlainAuthRequestUrlBuilder.java | 2 +- .../impl/SignedAuthRequestUrlBuilder.java | 2 +- .../impl/StaticAuthRequestOptionsService.java | 2 +- .../StaticClientConfigurationService.java | 2 +- .../StaticServerConfigurationService.java | 2 +- .../impl/StaticSingleIssuerService.java | 2 +- .../service/impl/ThirdPartyIssuerService.java | 2 +- .../service/impl/WebfingerIssuerService.java | 2 +- .../TestOAuth2AccessTokenImpl.java | 2 +- ...eBasedIntrospectionAuthoritiesGranter.java | 2 +- .../TestHybridClientConfigurationService.java | 2 +- .../TestHybridServerConfigurationService.java | 2 +- .../impl/TestPlainAuthRequestUrlBuilder.java | 2 +- .../impl/TestSignedAuthRequestUrlBuilder.java | 2 +- .../TestStaticClientConfigurationService.java | 2 +- .../TestStaticServerConfigurationService.java | 2 +- .../impl/TestThirdPartyIssuerService.java | 2 +- .../src/test/resources/test-context.xml | 30 +++++++++---------- openid-connect-common/pom.xml | 30 +++++++++---------- .../util/WebfingerURLNormalizer.java | 2 +- .../mitre/jose/keystore/JWKSetKeyStore.java | 2 +- .../JWTEncryptionAndDecryptionService.java | 2 +- ...aultJWTEncryptionAndDecryptionService.java | 2 +- .../JWTSigningAndValidationService.java | 2 +- .../service/impl/ClientKeyCacheService.java | 2 +- ...DefaultJWTSigningAndValidationService.java | 2 +- .../service/impl/JWKSetCacheService.java | 2 +- .../SymmetricKeyJWTValidatorCacheService.java | 2 +- .../model/AuthenticationHolderEntity.java | 2 +- .../oauth2/model/AuthorizationCodeEntity.java | 2 +- .../oauth2/model/ClientDetailsEntity.java | 2 +- .../oauth2/model/OAuth2AccessTokenEntity.java | 2 +- .../model/OAuth2RefreshTokenEntity.java | 2 +- .../mitre/oauth2/model/RegisteredClient.java | 2 +- .../oauth2/model/RegisteredClientFields.java | 2 +- .../oauth2/model/SavedUserAuthentication.java | 2 +- .../org/mitre/oauth2/model/SystemScope.java | 2 +- .../convert/JWEAlgorithmStringConverter.java | 2 +- .../JWEEncryptionMethodStringConverter.java | 2 +- .../model/convert/JWKSetStringConverter.java | 2 +- .../convert/JWSAlgorithmStringConverter.java | 2 +- .../model/convert/JWTStringConverter.java | 2 +- .../convert/JsonElementStringConverter.java | 2 +- .../convert/SerializableStringConverter.java | 2 +- ...SimpleGrantedAuthorityStringConverter.java | 2 +- .../AuthenticationHolderRepository.java | 2 +- .../AuthorizationCodeRepository.java | 2 +- .../repository/OAuth2ClientRepository.java | 2 +- .../repository/OAuth2TokenRepository.java | 2 +- .../repository/SystemScopeRepository.java | 2 +- .../service/ClientDetailsEntityService.java | 2 +- .../service/IntrospectionResultAssembler.java | 2 +- .../service/OAuth2TokenEntityService.java | 2 +- .../oauth2/service/SystemScopeService.java | 2 +- .../impl/DefaultClientUserDetailsService.java | 2 +- .../UriEncodedClientUserDetailsService.java | 2 +- .../ClientDetailsEntityJsonProcessor.java | 2 +- .../ConfigurationBeanLocaleResolver.java | 2 +- .../config/ConfigurationPropertiesBean.java | 2 +- .../openid/connect/config/JWKSetEditor.java | 2 +- .../connect/config/ServerConfiguration.java | 2 +- .../mitre/openid/connect/model/Address.java | 2 +- .../openid/connect/model/ApprovedSite.java | 2 +- .../openid/connect/model/BlacklistedSite.java | 2 +- .../openid/connect/model/DefaultAddress.java | 2 +- .../openid/connect/model/DefaultUserInfo.java | 2 +- .../model/OIDCAuthenticationToken.java | 2 +- .../connect/model/PairwiseIdentifier.java | 2 +- .../model/PendingOIDCAuthenticationToken.java | 2 +- .../mitre/openid/connect/model/UserInfo.java | 2 +- .../openid/connect/model/WhitelistedSite.java | 2 +- .../convert/JsonObjectStringConverter.java | 2 +- .../connect/repository/AddressRepository.java | 2 +- .../repository/ApprovedSiteRepository.java | 2 +- .../repository/BlacklistedSiteRepository.java | 2 +- .../PairwiseIdentifierRepository.java | 2 +- .../repository/UserInfoRepository.java | 2 +- .../repository/WhitelistedSiteRepository.java | 2 +- .../connect/service/ApprovedSiteService.java | 2 +- .../service/BlacklistedSiteService.java | 2 +- .../connect/service/LoginHintExtracter.java | 2 +- .../connect/service/MITREidDataService.java | 2 +- .../connect/service/OIDCTokenService.java | 2 +- .../service/PairwiseIdentiferService.java | 2 +- .../service/ScopeClaimTranslationService.java | 2 +- .../openid/connect/service/StatsService.java | 2 +- .../connect/service/UserInfoService.java | 2 +- .../service/WhitelistedSiteService.java | 2 +- .../mitre/openid/connect/view/JWKSetView.java | 2 +- .../connect/web/UserInfoInterceptor.java | 2 +- .../main/java/org/mitre/uma/model/Claim.java | 2 +- .../uma/model/ClaimProcessingResult.java | 2 +- .../java/org/mitre/uma/model/Permission.java | 2 +- .../org/mitre/uma/model/PermissionTicket.java | 2 +- .../main/java/org/mitre/uma/model/Policy.java | 2 +- .../java/org/mitre/uma/model/ResourceSet.java | 2 +- .../uma/model/SavedRegisteredClient.java | 2 +- .../RegisteredClientStringConverter.java | 2 +- .../uma/repository/PermissionRepository.java | 2 +- .../uma/repository/ResourceSetRepository.java | 2 +- .../uma/service/ClaimsProcessingService.java | 2 +- .../mitre/uma/service/PermissionService.java | 2 +- .../mitre/uma/service/ResourceSetService.java | 2 +- .../mitre/uma/service/UmaTokenService.java | 2 +- .../main/java/org/mitre/util/JsonUtils.java | 2 +- .../main/java/org/mitre/util/jpa/JpaUtil.java | 2 +- .../util/TestWebfingerURLNormalizer.java | 2 +- .../org/mitre/jose/TestJWKSetKeyStore.java | 2 +- ...aultJWTEncryptionAndDecryptionService.java | 2 +- .../oauth2/model/ClientDetailsEntityTest.java | 2 +- .../oauth2/model/RegisteredClientTest.java | 2 +- .../ClientDetailsEntityJsonProcessorTest.java | 2 +- .../ConfigurationPropertiesBeanTest.java | 2 +- .../config/ServerConfigurationTest.java | 2 +- openid-connect-server-webapp/pom.xml | 30 +++++++++---------- .../src/main/resources/log4j.xml | 30 +++++++++---------- .../webapp/WEB-INF/application-context.xml | 30 +++++++++---------- .../src/main/webapp/WEB-INF/authz-config.xml | 30 +++++++++---------- .../src/main/webapp/WEB-INF/crypto-config.xml | 30 +++++++++---------- .../src/main/webapp/WEB-INF/data-context.xml | 30 +++++++++---------- .../src/main/webapp/WEB-INF/jpa-config.xml | 30 +++++++++---------- .../src/main/webapp/WEB-INF/local-config.xml | 30 +++++++++---------- .../src/main/webapp/WEB-INF/server-config.xml | 30 +++++++++---------- .../main/webapp/WEB-INF/spring-servlet.xml | 30 +++++++++---------- .../src/main/webapp/WEB-INF/task-config.xml | 30 +++++++++---------- .../src/main/webapp/WEB-INF/user-context.xml | 30 +++++++++---------- .../src/main/webapp/WEB-INF/web.xml | 30 +++++++++---------- .../src/main/webapp/resources/js/admin.js | 2 +- .../src/main/webapp/resources/js/blacklist.js | 16 ++++++++++ .../src/main/webapp/resources/js/client.js | 2 +- .../src/main/webapp/resources/js/dynreg.js | 2 +- .../src/main/webapp/resources/js/grant.js | 2 +- .../resources/js/locale/en/messages.json | 4 +-- .../resources/js/locale/sv/messages.json | 4 +-- .../src/main/webapp/resources/js/rsreg.js | 2 +- .../src/main/webapp/resources/js/scope.js | 2 +- .../src/main/webapp/resources/js/token.js | 2 +- .../src/main/webapp/resources/js/whitelist.js | 2 +- openid-connect-server/pom.xml | 30 +++++++++---------- .../mitre/discovery/view/WebfingerView.java | 2 +- .../discovery/web/DiscoveryEndpoint.java | 2 +- .../exception/DuplicateClientIdException.java | 2 +- .../JpaAuthenticationHolderRepository.java | 2 +- .../impl/JpaAuthorizationCodeRepository.java | 2 +- .../impl/JpaOAuth2ClientRepository.java | 2 +- .../impl/JpaOAuth2TokenRepository.java | 2 +- .../impl/JpaSystemScopeRepository.java | 2 +- .../impl/BlacklistAwareRedirectResolver.java | 2 +- .../DefaultIntrospectionResultAssembler.java | 2 +- ...DefaultOAuth2AuthorizationCodeService.java | 2 +- ...faultOAuth2ClientDetailsEntityService.java | 2 +- .../DefaultOAuth2ProviderTokenService.java | 2 +- .../impl/DefaultSystemScopeService.java | 2 +- .../oauth2/token/ChainedTokenGranter.java | 2 +- .../token/JWTAssertionTokenGranter.java | 2 +- ...turedScopeAwareOAuth2RequestValidator.java | 2 +- .../org/mitre/oauth2/view/TokenApiView.java | 2 +- .../oauth2/web/AuthenticationUtilities.java | 2 +- .../java/org/mitre/oauth2/web/CorsFilter.java | 2 +- .../oauth2/web/IntrospectionEndpoint.java | 2 +- .../oauth2/web/OAuth2ExceptionHandler.java | 2 +- .../web/OAuthConfirmationController.java | 2 +- .../mitre/oauth2/web/RevocationEndpoint.java | 2 +- .../java/org/mitre/oauth2/web/ScopeAPI.java | 2 +- .../java/org/mitre/oauth2/web/TokenAPI.java | 2 +- ...JWTBearerAssertionAuthenticationToken.java | 2 +- .../JWTBearerAuthenticationProvider.java | 2 +- ...rerClientAssertionTokenEndpointFilter.java | 2 +- .../connect/config/JsonMessageSource.java | 2 +- .../exception/ValidationException.java | 2 +- .../filter/AuthorizationRequestFilter.java | 2 +- .../filter/MultiUrlRequestMatcher.java | 2 +- .../repository/impl/JpaAddressRepository.java | 2 +- .../impl/JpaApprovedSiteRepository.java | 2 +- .../impl/JpaBlacklistedSiteRepository.java | 2 +- .../impl/JpaPairwiseIdentifierRepository.java | 2 +- .../impl/JpaUserInfoRepository.java | 2 +- .../impl/JpaWhitelistedSiteRepository.java | 2 +- .../request/ConnectOAuth2RequestFactory.java | 2 +- .../request/ConnectRequestParameters.java | 2 +- .../impl/DefaultApprovedSiteService.java | 2 +- .../impl/DefaultBlacklistedSiteService.java | 2 +- .../service/impl/DefaultOIDCTokenService.java | 2 +- .../DefaultScopeClaimTranslationService.java | 2 +- .../service/impl/DefaultStatsService.java | 2 +- .../service/impl/DefaultUserInfoService.java | 2 +- .../impl/DefaultWhitelistedSiteService.java | 2 +- .../service/impl/DummyResourceSetService.java | 2 +- .../impl/MITREidDataServiceSupport.java | 2 +- .../service/impl/MITREidDataService_1_0.java | 2 +- .../service/impl/MITREidDataService_1_1.java | 2 +- .../service/impl/MITREidDataService_1_2.java | 2 +- .../impl/MatchLoginHintsAgainstUsers.java | 2 +- .../service/impl/PassAllLoginHints.java | 2 +- .../impl/RemoveLoginHintsWithHTTP.java | 2 +- .../impl/UUIDPairwiseIdentiferService.java | 2 +- .../connect/token/ConnectTokenEnhancer.java | 2 +- .../token/TofuUserApprovalHandler.java | 2 +- .../openid/connect/util/IdTokenHashUtils.java | 2 +- .../view/AbstractClientEntityView.java | 2 +- .../view/ClientEntityViewForAdmins.java | 2 +- .../view/ClientEntityViewForUsers.java | 2 +- .../view/ClientInformationResponseView.java | 2 +- .../openid/connect/view/HttpCodeView.java | 2 +- .../connect/view/JsonApprovedSiteView.java | 2 +- .../openid/connect/view/JsonEntityView.java | 2 +- .../openid/connect/view/JsonErrorView.java | 2 +- .../openid/connect/view/UserInfoJWTView.java | 2 +- .../openid/connect/view/UserInfoView.java | 2 +- .../openid/connect/web/ApprovedSiteAPI.java | 2 +- .../web/AuthenticationTimeStamper.java | 2 +- .../openid/connect/web/BlacklistAPI.java | 2 +- .../mitre/openid/connect/web/ClientAPI.java | 2 +- .../org/mitre/openid/connect/web/DataAPI.java | 2 +- .../DynamicClientRegistrationEndpoint.java | 2 +- .../connect/web/JWKSetPublishingEndpoint.java | 2 +- ...ProtectedResourceRegistrationEndpoint.java | 2 +- .../openid/connect/web/RootController.java | 2 +- .../connect/web/ServerConfigInterceptor.java | 2 +- .../mitre/openid/connect/web/StatsAPI.java | 2 +- .../openid/connect/web/UserInfoEndpoint.java | 2 +- .../openid/connect/web/WhitelistAPI.java | 2 +- .../TestBlacklistAwareRedirectResolver.java | 2 +- ...stDefaultIntrospectionResultAssembler.java | 2 +- ...faultOAuth2ClientDetailsEntityService.java | 2 +- ...TestDefaultOAuth2ProviderTokenService.java | 2 +- .../impl/TestDefaultSystemScopeService.java | 2 +- .../impl/TestDefaultApprovedSiteService.java | 2 +- .../TestDefaultBlacklistedSiteService.java | 2 +- .../service/impl/TestDefaultStatsService.java | 2 +- .../impl/TestDefaultUserInfoService.java | 2 +- .../TestDefaultWhitelistedSiteService.java | 2 +- .../impl/TestMITREidDataService_1_0.java | 2 +- .../impl/TestMITREidDataService_1_1.java | 2 +- .../impl/TestMITREidDataService_1_2.java | 2 +- .../TestUUIDPairwiseIdentiferService.java | 2 +- .../connect/util/TestIdTokenHashUtils.java | 2 +- pom.xml | 30 +++++++++---------- uma-server-webapp/pom.xml | 30 +++++++++---------- .../service/impl/MITREidDataService_1_2.java | 2 +- .../webapp/WEB-INF/application-context.xml | 30 +++++++++---------- .../src/main/webapp/WEB-INF/server-config.xml | 30 +++++++++---------- .../src/main/webapp/WEB-INF/user-context.xml | 30 +++++++++---------- .../src/main/webapp/resources/js/admin.js | 2 +- .../src/main/webapp/resources/js/policy.js | 2 +- uma-server/pom.xml | 30 +++++++++---------- .../impl/JpaPermissionRepository.java | 2 +- .../impl/JpaResourceSetRepository.java | 2 +- .../impl/DefaultPermissionService.java | 2 +- .../impl/DefaultResourceSetService.java | 2 +- .../service/impl/DefaultUmaTokenService.java | 2 +- .../impl/JpaRegisteredClientService.java | 2 +- .../impl/MatchAllClaimsOnAnyPolicy.java | 2 +- .../util/ExternalLoginAuthoritiesMapper.java | 2 +- .../ResourceSetEntityAbbreviatedView.java | 2 +- .../mitre/uma/view/ResourceSetEntityView.java | 2 +- .../uma/web/AuthorizationRequestEndpoint.java | 2 +- .../uma/web/ClaimsCollectionEndpoint.java | 2 +- .../web/PermissionRegistrationEndpoint.java | 2 +- .../java/org/mitre/uma/web/PolicyAPI.java | 2 +- .../web/ResourceSetRegistrationEndpoint.java | 2 +- .../mitre/uma/web/UmaDiscoveryEndpoint.java | 2 +- .../mitre/uma/web/UserClaimSearchHelper.java | 2 +- .../impl/TestDefaultPermissionService.java | 2 +- .../impl/TestDefaultResourceSetService.java | 2 +- 302 files changed, 655 insertions(+), 639 deletions(-) diff --git a/README.md b/README.md index deafbbd484..0983ceecf1 100644 --- a/README.md +++ b/README.md @@ -30,4 +30,4 @@ The authors and key contributors of the project include: Copyright ©2015, [The MITRE Corporation](http://www.mitre.org/) - and the [MIT Kerberos and Internet Trust Consortium](http://kit.mit.edu/). Licensed under the Apache 2.0 license, for details see `LICENSE.txt`. + and the [MIT Internet Trust Consortium](http://kit.mit.edu/). Licensed under the Apache 2.0 license, for details see `LICENSE.txt`. diff --git a/checkstyle.xml b/checkstyle.xml index 69f93d97ca..2414ab2702 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -1,20 +1,20 @@ + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> diff --git a/openid-connect-client/pom.xml b/openid-connect-client/pom.xml index 5d5c44beea..162d34ad1d 100644 --- a/openid-connect-client/pom.xml +++ b/openid-connect-client/pom.xml @@ -1,20 +1,20 @@ + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> 4.0.0 diff --git a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/IntrospectingTokenService.java b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/IntrospectingTokenService.java index 024301d005..2b496217d5 100644 --- a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/IntrospectingTokenService.java +++ b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/IntrospectingTokenService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/OAuth2AccessTokenImpl.java b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/OAuth2AccessTokenImpl.java index 3e78e4b9c9..ab190ff950 100644 --- a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/OAuth2AccessTokenImpl.java +++ b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/OAuth2AccessTokenImpl.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/IntrospectionAuthorityGranter.java b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/IntrospectionAuthorityGranter.java index d9559cefeb..fe5184cce2 100644 --- a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/IntrospectionAuthorityGranter.java +++ b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/IntrospectionAuthorityGranter.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/IntrospectionConfigurationService.java b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/IntrospectionConfigurationService.java index e844cc7051..2aca06854a 100644 --- a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/IntrospectionConfigurationService.java +++ b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/IntrospectionConfigurationService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/JWTParsingIntrospectionConfigurationService.java b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/JWTParsingIntrospectionConfigurationService.java index 613364c51f..bea5974bba 100644 --- a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/JWTParsingIntrospectionConfigurationService.java +++ b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/JWTParsingIntrospectionConfigurationService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/ScopeBasedIntrospectionAuthoritiesGranter.java b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/ScopeBasedIntrospectionAuthoritiesGranter.java index 5e29567ca7..33351be7b5 100644 --- a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/ScopeBasedIntrospectionAuthoritiesGranter.java +++ b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/ScopeBasedIntrospectionAuthoritiesGranter.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/SimpleIntrospectionAuthorityGranter.java b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/SimpleIntrospectionAuthorityGranter.java index 6ddb0a52b0..02d3f24d9b 100644 --- a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/SimpleIntrospectionAuthorityGranter.java +++ b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/SimpleIntrospectionAuthorityGranter.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/StaticIntrospectionConfigurationService.java b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/StaticIntrospectionConfigurationService.java index 86dd38f8c2..64cee6be9a 100644 --- a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/StaticIntrospectionConfigurationService.java +++ b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/StaticIntrospectionConfigurationService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/NamedAdminAuthoritiesMapper.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/NamedAdminAuthoritiesMapper.java index 82970e42f4..2b31e6fc6b 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/NamedAdminAuthoritiesMapper.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/NamedAdminAuthoritiesMapper.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java index dbf0ab50fd..28819c0aba 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationProvider.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationProvider.java index a28bb19869..b85336115e 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationProvider.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationProvider.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthoritiesMapper.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthoritiesMapper.java index d16dea4e15..bf3cb8e2c6 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthoritiesMapper.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthoritiesMapper.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/StaticPrefixTargetLinkURIChecker.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/StaticPrefixTargetLinkURIChecker.java index 466fa82ce7..4320b7d43c 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/StaticPrefixTargetLinkURIChecker.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/StaticPrefixTargetLinkURIChecker.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/SubjectIssuerGrantedAuthority.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/SubjectIssuerGrantedAuthority.java index d9686fe3be..e75e96d9be 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/SubjectIssuerGrantedAuthority.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/SubjectIssuerGrantedAuthority.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/TargetLinkURIChecker.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/TargetLinkURIChecker.java index 69baca9fdc..3794c2b324 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/TargetLinkURIChecker.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/TargetLinkURIChecker.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/UserInfoFetcher.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/UserInfoFetcher.java index 062eb5819a..edbe6a0edb 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/UserInfoFetcher.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/UserInfoFetcher.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/keypublisher/ClientKeyPublisher.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/keypublisher/ClientKeyPublisher.java index d7b9246b4d..8eab18c9ca 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/keypublisher/ClientKeyPublisher.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/keypublisher/ClientKeyPublisher.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/keypublisher/ClientKeyPublisherMapping.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/keypublisher/ClientKeyPublisherMapping.java index 3cdab0ed46..882a36366c 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/keypublisher/ClientKeyPublisherMapping.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/keypublisher/ClientKeyPublisherMapping.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/keypublisher/JwkViewResolver.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/keypublisher/JwkViewResolver.java index 6d849c2e99..e345447277 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/keypublisher/JwkViewResolver.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/keypublisher/JwkViewResolver.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/model/IssuerServiceResponse.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/model/IssuerServiceResponse.java index df97f1cfaf..ef69b5e9a2 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/model/IssuerServiceResponse.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/model/IssuerServiceResponse.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/AuthRequestOptionsService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/AuthRequestOptionsService.java index 35f9cfdfcd..3a6b927c8c 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/AuthRequestOptionsService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/AuthRequestOptionsService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/AuthRequestUrlBuilder.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/AuthRequestUrlBuilder.java index 869c33cc5a..0342c2b166 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/AuthRequestUrlBuilder.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/AuthRequestUrlBuilder.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/ClientConfigurationService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/ClientConfigurationService.java index 49bfed5042..6a54d043e1 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/ClientConfigurationService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/ClientConfigurationService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/IssuerService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/IssuerService.java index 858f7175a7..e84ff27501 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/IssuerService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/IssuerService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/RegisteredClientService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/RegisteredClientService.java index 048176ce5e..9e1dbbf6ce 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/RegisteredClientService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/RegisteredClientService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/ServerConfigurationService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/ServerConfigurationService.java index cef75fb698..fa83937698 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/ServerConfigurationService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/ServerConfigurationService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/DynamicRegistrationClientConfigurationService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/DynamicRegistrationClientConfigurationService.java index 5ea5a0522f..6b0ca29698 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/DynamicRegistrationClientConfigurationService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/DynamicRegistrationClientConfigurationService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/DynamicServerConfigurationService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/DynamicServerConfigurationService.java index d7ce15aa69..34dafc9bca 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/DynamicServerConfigurationService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/DynamicServerConfigurationService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/EncryptedAuthRequestUrlBuilder.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/EncryptedAuthRequestUrlBuilder.java index 07fdf42587..f9b1813455 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/EncryptedAuthRequestUrlBuilder.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/EncryptedAuthRequestUrlBuilder.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/HybridClientConfigurationService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/HybridClientConfigurationService.java index 94b4b8e7d9..20a8b6db90 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/HybridClientConfigurationService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/HybridClientConfigurationService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/HybridIssuerService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/HybridIssuerService.java index 1e96da0acd..4e222357a9 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/HybridIssuerService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/HybridIssuerService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/HybridServerConfigurationService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/HybridServerConfigurationService.java index cdd18778c6..fe3418bbf9 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/HybridServerConfigurationService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/HybridServerConfigurationService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/InMemoryRegisteredClientService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/InMemoryRegisteredClientService.java index 8963016ef1..2b0e12aa70 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/InMemoryRegisteredClientService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/InMemoryRegisteredClientService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/JsonFileRegisteredClientService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/JsonFileRegisteredClientService.java index 2a511ed20a..89d7f61715 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/JsonFileRegisteredClientService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/JsonFileRegisteredClientService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/PlainAuthRequestUrlBuilder.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/PlainAuthRequestUrlBuilder.java index ea0b09bf74..f1550b0589 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/PlainAuthRequestUrlBuilder.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/PlainAuthRequestUrlBuilder.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/SignedAuthRequestUrlBuilder.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/SignedAuthRequestUrlBuilder.java index 20d13ca48e..f53afc5741 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/SignedAuthRequestUrlBuilder.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/SignedAuthRequestUrlBuilder.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticAuthRequestOptionsService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticAuthRequestOptionsService.java index 134c67edce..69ff3d6fca 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticAuthRequestOptionsService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticAuthRequestOptionsService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticClientConfigurationService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticClientConfigurationService.java index 69edf2b7b2..77aaf1651a 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticClientConfigurationService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticClientConfigurationService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticServerConfigurationService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticServerConfigurationService.java index 4bb519e706..2aa1366818 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticServerConfigurationService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticServerConfigurationService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticSingleIssuerService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticSingleIssuerService.java index aefcae9478..966c2d4685 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticSingleIssuerService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticSingleIssuerService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/ThirdPartyIssuerService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/ThirdPartyIssuerService.java index f1c89793f9..87d526cea8 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/ThirdPartyIssuerService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/ThirdPartyIssuerService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/WebfingerIssuerService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/WebfingerIssuerService.java index 383df2e003..79c43bc21d 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/WebfingerIssuerService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/WebfingerIssuerService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/test/java/org/mitre/oauth2/introspectingfilter/TestOAuth2AccessTokenImpl.java b/openid-connect-client/src/test/java/org/mitre/oauth2/introspectingfilter/TestOAuth2AccessTokenImpl.java index 70ee62cd91..7069ab9c0e 100644 --- a/openid-connect-client/src/test/java/org/mitre/oauth2/introspectingfilter/TestOAuth2AccessTokenImpl.java +++ b/openid-connect-client/src/test/java/org/mitre/oauth2/introspectingfilter/TestOAuth2AccessTokenImpl.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/test/java/org/mitre/oauth2/introspectingfilter/service/impl/TestScopeBasedIntrospectionAuthoritiesGranter.java b/openid-connect-client/src/test/java/org/mitre/oauth2/introspectingfilter/service/impl/TestScopeBasedIntrospectionAuthoritiesGranter.java index 20952e79b6..d485cddb98 100644 --- a/openid-connect-client/src/test/java/org/mitre/oauth2/introspectingfilter/service/impl/TestScopeBasedIntrospectionAuthoritiesGranter.java +++ b/openid-connect-client/src/test/java/org/mitre/oauth2/introspectingfilter/service/impl/TestScopeBasedIntrospectionAuthoritiesGranter.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestHybridClientConfigurationService.java b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestHybridClientConfigurationService.java index 53fe382e0c..574aaab4d3 100644 --- a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestHybridClientConfigurationService.java +++ b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestHybridClientConfigurationService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestHybridServerConfigurationService.java b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestHybridServerConfigurationService.java index fc0a552926..76fde2ae9a 100644 --- a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestHybridServerConfigurationService.java +++ b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestHybridServerConfigurationService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestPlainAuthRequestUrlBuilder.java b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestPlainAuthRequestUrlBuilder.java index af4ea92096..bd73832fd1 100644 --- a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestPlainAuthRequestUrlBuilder.java +++ b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestPlainAuthRequestUrlBuilder.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestSignedAuthRequestUrlBuilder.java b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestSignedAuthRequestUrlBuilder.java index 8f2663e380..0e38a54d5f 100644 --- a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestSignedAuthRequestUrlBuilder.java +++ b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestSignedAuthRequestUrlBuilder.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestStaticClientConfigurationService.java b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestStaticClientConfigurationService.java index c6c4c323d8..c58241ef29 100644 --- a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestStaticClientConfigurationService.java +++ b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestStaticClientConfigurationService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestStaticServerConfigurationService.java b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestStaticServerConfigurationService.java index e499119956..7272b8e3b5 100644 --- a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestStaticServerConfigurationService.java +++ b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestStaticServerConfigurationService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestThirdPartyIssuerService.java b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestThirdPartyIssuerService.java index b315f2075e..18408030e0 100644 --- a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestThirdPartyIssuerService.java +++ b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestThirdPartyIssuerService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-client/src/test/resources/test-context.xml b/openid-connect-client/src/test/resources/test-context.xml index 8ed89f7282..21285abe74 100644 --- a/openid-connect-client/src/test/resources/test-context.xml +++ b/openid-connect-client/src/test/resources/test-context.xml @@ -1,20 +1,20 @@ + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> 4.0.0 diff --git a/openid-connect-common/src/main/java/org/mitre/discovery/util/WebfingerURLNormalizer.java b/openid-connect-common/src/main/java/org/mitre/discovery/util/WebfingerURLNormalizer.java index 08bed78d02..c2d429a837 100644 --- a/openid-connect-common/src/main/java/org/mitre/discovery/util/WebfingerURLNormalizer.java +++ b/openid-connect-common/src/main/java/org/mitre/discovery/util/WebfingerURLNormalizer.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/jose/keystore/JWKSetKeyStore.java b/openid-connect-common/src/main/java/org/mitre/jose/keystore/JWKSetKeyStore.java index bbe3b73194..0f522b352c 100644 --- a/openid-connect-common/src/main/java/org/mitre/jose/keystore/JWKSetKeyStore.java +++ b/openid-connect-common/src/main/java/org/mitre/jose/keystore/JWKSetKeyStore.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/encryption/service/JWTEncryptionAndDecryptionService.java b/openid-connect-common/src/main/java/org/mitre/jwt/encryption/service/JWTEncryptionAndDecryptionService.java index a01c5b309a..3e2f6a99e0 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/encryption/service/JWTEncryptionAndDecryptionService.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/encryption/service/JWTEncryptionAndDecryptionService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/encryption/service/impl/DefaultJWTEncryptionAndDecryptionService.java b/openid-connect-common/src/main/java/org/mitre/jwt/encryption/service/impl/DefaultJWTEncryptionAndDecryptionService.java index f9d08b74aa..648af8a0d6 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/encryption/service/impl/DefaultJWTEncryptionAndDecryptionService.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/encryption/service/impl/DefaultJWTEncryptionAndDecryptionService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/JWTSigningAndValidationService.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/JWTSigningAndValidationService.java index 5d24fe483e..0ec5865cff 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/JWTSigningAndValidationService.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/JWTSigningAndValidationService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/ClientKeyCacheService.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/ClientKeyCacheService.java index e17a6bb773..5f2ae1b9a3 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/ClientKeyCacheService.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/ClientKeyCacheService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DefaultJWTSigningAndValidationService.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DefaultJWTSigningAndValidationService.java index 54e89f43f5..1cbe6914f0 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DefaultJWTSigningAndValidationService.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DefaultJWTSigningAndValidationService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/JWKSetCacheService.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/JWKSetCacheService.java index 1b1216390c..e8c224277d 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/JWKSetCacheService.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/JWKSetCacheService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/SymmetricKeyJWTValidatorCacheService.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/SymmetricKeyJWTValidatorCacheService.java index 02793ae64f..d7e50eaa9b 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/SymmetricKeyJWTValidatorCacheService.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/SymmetricKeyJWTValidatorCacheService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/AuthenticationHolderEntity.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/AuthenticationHolderEntity.java index 061b16a5dd..bb9bff9f71 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/AuthenticationHolderEntity.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/AuthenticationHolderEntity.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/AuthorizationCodeEntity.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/AuthorizationCodeEntity.java index 46a573f86b..16d5f40999 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/AuthorizationCodeEntity.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/AuthorizationCodeEntity.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/ClientDetailsEntity.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/ClientDetailsEntity.java index 4774856d0d..6198845f1e 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/ClientDetailsEntity.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/ClientDetailsEntity.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2AccessTokenEntity.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2AccessTokenEntity.java index b642f64e5e..ef58e96cba 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2AccessTokenEntity.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2AccessTokenEntity.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2RefreshTokenEntity.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2RefreshTokenEntity.java index d91a7db1db..6f6544ee9d 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2RefreshTokenEntity.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2RefreshTokenEntity.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClient.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClient.java index 62311c8490..04887eb0bc 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClient.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClient.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClientFields.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClientFields.java index 217c282960..18acd0e0a2 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClientFields.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClientFields.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/SavedUserAuthentication.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/SavedUserAuthentication.java index 4cf6aab15b..2757714685 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/SavedUserAuthentication.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/SavedUserAuthentication.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/SystemScope.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/SystemScope.java index 01f55ef31a..311d661302 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/SystemScope.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/SystemScope.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JWEAlgorithmStringConverter.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JWEAlgorithmStringConverter.java index 1711c839bd..5eda3a476c 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JWEAlgorithmStringConverter.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JWEAlgorithmStringConverter.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JWEEncryptionMethodStringConverter.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JWEEncryptionMethodStringConverter.java index 80eafecdf1..da69340cd0 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JWEEncryptionMethodStringConverter.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JWEEncryptionMethodStringConverter.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JWKSetStringConverter.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JWKSetStringConverter.java index e9bae0c90c..ae9fd7b3d1 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JWKSetStringConverter.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JWKSetStringConverter.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JWSAlgorithmStringConverter.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JWSAlgorithmStringConverter.java index 9d40edee62..93db8e87a7 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JWSAlgorithmStringConverter.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JWSAlgorithmStringConverter.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JWTStringConverter.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JWTStringConverter.java index cf561fa312..adfe15dc1c 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JWTStringConverter.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JWTStringConverter.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JsonElementStringConverter.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JsonElementStringConverter.java index 7369db9f6c..1364694f8b 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JsonElementStringConverter.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/JsonElementStringConverter.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/SerializableStringConverter.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/SerializableStringConverter.java index 3fb30098cc..558c90b304 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/SerializableStringConverter.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/SerializableStringConverter.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/SimpleGrantedAuthorityStringConverter.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/SimpleGrantedAuthorityStringConverter.java index 7a33d48f14..3102136b27 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/SimpleGrantedAuthorityStringConverter.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/SimpleGrantedAuthorityStringConverter.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthenticationHolderRepository.java b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthenticationHolderRepository.java index 6c11942cbb..e6eb6c6627 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthenticationHolderRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthenticationHolderRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthorizationCodeRepository.java b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthorizationCodeRepository.java index baa0ebc8fe..5ef8f50b9f 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthorizationCodeRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthorizationCodeRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2ClientRepository.java b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2ClientRepository.java index 888daf0dce..80d0eaf604 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2ClientRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2ClientRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2TokenRepository.java b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2TokenRepository.java index 3f32a938b9..2feccaeb7b 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2TokenRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2TokenRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/SystemScopeRepository.java b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/SystemScopeRepository.java index d16cfa3d2f..77f7d745db 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/SystemScopeRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/SystemScopeRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/service/ClientDetailsEntityService.java b/openid-connect-common/src/main/java/org/mitre/oauth2/service/ClientDetailsEntityService.java index aa2d83ca0a..6fdcddc786 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/service/ClientDetailsEntityService.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/service/ClientDetailsEntityService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/service/IntrospectionResultAssembler.java b/openid-connect-common/src/main/java/org/mitre/oauth2/service/IntrospectionResultAssembler.java index 70d1c67107..53869c668a 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/service/IntrospectionResultAssembler.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/service/IntrospectionResultAssembler.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/service/OAuth2TokenEntityService.java b/openid-connect-common/src/main/java/org/mitre/oauth2/service/OAuth2TokenEntityService.java index ed7f3a105b..f5d498a34d 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/service/OAuth2TokenEntityService.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/service/OAuth2TokenEntityService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/service/SystemScopeService.java b/openid-connect-common/src/main/java/org/mitre/oauth2/service/SystemScopeService.java index c3521d3ecf..fdde1cb8cb 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/service/SystemScopeService.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/service/SystemScopeService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/service/impl/DefaultClientUserDetailsService.java b/openid-connect-common/src/main/java/org/mitre/oauth2/service/impl/DefaultClientUserDetailsService.java index 1686243327..2baf5a6a74 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/service/impl/DefaultClientUserDetailsService.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/service/impl/DefaultClientUserDetailsService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/service/impl/UriEncodedClientUserDetailsService.java b/openid-connect-common/src/main/java/org/mitre/oauth2/service/impl/UriEncodedClientUserDetailsService.java index 2dd015bd46..d0f21b22d0 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/service/impl/UriEncodedClientUserDetailsService.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/service/impl/UriEncodedClientUserDetailsService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/ClientDetailsEntityJsonProcessor.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/ClientDetailsEntityJsonProcessor.java index 59157623f5..21d8a85b45 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/ClientDetailsEntityJsonProcessor.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/ClientDetailsEntityJsonProcessor.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationBeanLocaleResolver.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationBeanLocaleResolver.java index 316a378494..3c074a66c2 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationBeanLocaleResolver.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationBeanLocaleResolver.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationPropertiesBean.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationPropertiesBean.java index f03df8d671..4b70d9455c 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationPropertiesBean.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationPropertiesBean.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/config/JWKSetEditor.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/config/JWKSetEditor.java index ddf2df2803..9857211534 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/config/JWKSetEditor.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/config/JWKSetEditor.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ServerConfiguration.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ServerConfiguration.java index 6e7784828c..ffc4c2c81a 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ServerConfiguration.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ServerConfiguration.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/Address.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/Address.java index a644a02465..0110f45a0b 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/Address.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/Address.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ApprovedSite.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ApprovedSite.java index 0c644bbbb4..db149db342 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ApprovedSite.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ApprovedSite.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/BlacklistedSite.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/BlacklistedSite.java index 0cbdecc814..e61f8fb1a0 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/BlacklistedSite.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/BlacklistedSite.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultAddress.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultAddress.java index b4992ae346..e28f011336 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultAddress.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultAddress.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultUserInfo.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultUserInfo.java index 630d42d0de..3c89306bda 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultUserInfo.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultUserInfo.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/OIDCAuthenticationToken.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/OIDCAuthenticationToken.java index 9f526d2416..a78f2c8c94 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/OIDCAuthenticationToken.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/OIDCAuthenticationToken.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/PairwiseIdentifier.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/PairwiseIdentifier.java index a1391df1eb..f28e37849c 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/PairwiseIdentifier.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/PairwiseIdentifier.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/PendingOIDCAuthenticationToken.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/PendingOIDCAuthenticationToken.java index 26f0bb1545..c91c1b13dd 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/PendingOIDCAuthenticationToken.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/PendingOIDCAuthenticationToken.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/UserInfo.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/UserInfo.java index c25c156507..0815224a8f 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/UserInfo.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/UserInfo.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/WhitelistedSite.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/WhitelistedSite.java index a89215882b..817732e347 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/WhitelistedSite.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/WhitelistedSite.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/convert/JsonObjectStringConverter.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/convert/JsonObjectStringConverter.java index 1578760ff1..e420ec97e6 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/convert/JsonObjectStringConverter.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/convert/JsonObjectStringConverter.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/AddressRepository.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/AddressRepository.java index c4d09c0409..63dedf4a76 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/AddressRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/AddressRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/ApprovedSiteRepository.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/ApprovedSiteRepository.java index fe57f44f93..61bb84ef55 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/ApprovedSiteRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/ApprovedSiteRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/BlacklistedSiteRepository.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/BlacklistedSiteRepository.java index b541d8e2d0..9849fe7c49 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/BlacklistedSiteRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/BlacklistedSiteRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/PairwiseIdentifierRepository.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/PairwiseIdentifierRepository.java index 0bbf4d4fff..2245bdbcde 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/PairwiseIdentifierRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/PairwiseIdentifierRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/UserInfoRepository.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/UserInfoRepository.java index 02f91b2f04..481406e69a 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/UserInfoRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/UserInfoRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/WhitelistedSiteRepository.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/WhitelistedSiteRepository.java index d81314688e..16b85aadd2 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/WhitelistedSiteRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/WhitelistedSiteRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/ApprovedSiteService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/ApprovedSiteService.java index d3cd7a72f7..a5352add0b 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/ApprovedSiteService.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/ApprovedSiteService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/BlacklistedSiteService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/BlacklistedSiteService.java index 15bdc54feb..e08b7fd39d 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/BlacklistedSiteService.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/BlacklistedSiteService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/LoginHintExtracter.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/LoginHintExtracter.java index 58955b44fd..a6768bab74 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/LoginHintExtracter.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/LoginHintExtracter.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/MITREidDataService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/MITREidDataService.java index 7067950127..ea8b1b2de1 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/MITREidDataService.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/MITREidDataService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/OIDCTokenService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/OIDCTokenService.java index 859a66d7a1..09e96f8405 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/OIDCTokenService.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/OIDCTokenService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/PairwiseIdentiferService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/PairwiseIdentiferService.java index 3d4c14d15e..4c02d21465 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/PairwiseIdentiferService.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/PairwiseIdentiferService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/ScopeClaimTranslationService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/ScopeClaimTranslationService.java index 6b38453659..71a41f8d59 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/ScopeClaimTranslationService.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/ScopeClaimTranslationService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/StatsService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/StatsService.java index 0d92b3bdd3..304b75e56d 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/StatsService.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/StatsService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/UserInfoService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/UserInfoService.java index 45879ee339..202e6358f6 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/UserInfoService.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/UserInfoService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/WhitelistedSiteService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/WhitelistedSiteService.java index 9e38a334ee..10978a1b73 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/WhitelistedSiteService.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/WhitelistedSiteService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/view/JWKSetView.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/view/JWKSetView.java index db599ff60e..551e6778ba 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/view/JWKSetView.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/view/JWKSetView.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/web/UserInfoInterceptor.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/web/UserInfoInterceptor.java index 7cddd52a16..d7ed4103fd 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/web/UserInfoInterceptor.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/web/UserInfoInterceptor.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/Claim.java b/openid-connect-common/src/main/java/org/mitre/uma/model/Claim.java index 51390e3dc5..21c54070cf 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/Claim.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/Claim.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/ClaimProcessingResult.java b/openid-connect-common/src/main/java/org/mitre/uma/model/ClaimProcessingResult.java index c1ca4b9dd1..62c3914518 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/ClaimProcessingResult.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/ClaimProcessingResult.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/Permission.java b/openid-connect-common/src/main/java/org/mitre/uma/model/Permission.java index 3e6509b7e8..58b5eb8ddb 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/Permission.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/Permission.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/PermissionTicket.java b/openid-connect-common/src/main/java/org/mitre/uma/model/PermissionTicket.java index 25848b35e3..d583647eaf 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/PermissionTicket.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/PermissionTicket.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/Policy.java b/openid-connect-common/src/main/java/org/mitre/uma/model/Policy.java index 3d1870a292..d3fd446c98 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/Policy.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/Policy.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/ResourceSet.java b/openid-connect-common/src/main/java/org/mitre/uma/model/ResourceSet.java index 3097ec3a26..afde38f25e 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/ResourceSet.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/ResourceSet.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/SavedRegisteredClient.java b/openid-connect-common/src/main/java/org/mitre/uma/model/SavedRegisteredClient.java index 25ed8723f7..58281e9081 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/SavedRegisteredClient.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/SavedRegisteredClient.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/convert/RegisteredClientStringConverter.java b/openid-connect-common/src/main/java/org/mitre/uma/model/convert/RegisteredClientStringConverter.java index 2cdb24a70e..6c5ff542a9 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/convert/RegisteredClientStringConverter.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/convert/RegisteredClientStringConverter.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/uma/repository/PermissionRepository.java b/openid-connect-common/src/main/java/org/mitre/uma/repository/PermissionRepository.java index 30fa77a5ea..bd17687f33 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/repository/PermissionRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/repository/PermissionRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/uma/repository/ResourceSetRepository.java b/openid-connect-common/src/main/java/org/mitre/uma/repository/ResourceSetRepository.java index 997e2f15ba..b9bb0a8ff1 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/repository/ResourceSetRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/repository/ResourceSetRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java b/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java index 1d05b8c7e0..c007209546 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/uma/service/PermissionService.java b/openid-connect-common/src/main/java/org/mitre/uma/service/PermissionService.java index 0c633cebda..79f0726f6e 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/service/PermissionService.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/service/PermissionService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/uma/service/ResourceSetService.java b/openid-connect-common/src/main/java/org/mitre/uma/service/ResourceSetService.java index fd64e83cff..4c57c40284 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/service/ResourceSetService.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/service/ResourceSetService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/uma/service/UmaTokenService.java b/openid-connect-common/src/main/java/org/mitre/uma/service/UmaTokenService.java index 4a85ca9e76..4846df2df5 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/service/UmaTokenService.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/service/UmaTokenService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/util/JsonUtils.java b/openid-connect-common/src/main/java/org/mitre/util/JsonUtils.java index 7e2002649a..ce959a6aee 100644 --- a/openid-connect-common/src/main/java/org/mitre/util/JsonUtils.java +++ b/openid-connect-common/src/main/java/org/mitre/util/JsonUtils.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/main/java/org/mitre/util/jpa/JpaUtil.java b/openid-connect-common/src/main/java/org/mitre/util/jpa/JpaUtil.java index 835e4be1d5..bddcb62262 100644 --- a/openid-connect-common/src/main/java/org/mitre/util/jpa/JpaUtil.java +++ b/openid-connect-common/src/main/java/org/mitre/util/jpa/JpaUtil.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/test/java/org/mitre/discovery/util/TestWebfingerURLNormalizer.java b/openid-connect-common/src/test/java/org/mitre/discovery/util/TestWebfingerURLNormalizer.java index edde15cc0d..ba0520a222 100644 --- a/openid-connect-common/src/test/java/org/mitre/discovery/util/TestWebfingerURLNormalizer.java +++ b/openid-connect-common/src/test/java/org/mitre/discovery/util/TestWebfingerURLNormalizer.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/test/java/org/mitre/jose/TestJWKSetKeyStore.java b/openid-connect-common/src/test/java/org/mitre/jose/TestJWKSetKeyStore.java index a2dd2d4435..944f26bbff 100644 --- a/openid-connect-common/src/test/java/org/mitre/jose/TestJWKSetKeyStore.java +++ b/openid-connect-common/src/test/java/org/mitre/jose/TestJWKSetKeyStore.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java b/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java index 807f5f7591..e3ef98b63e 100644 --- a/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java +++ b/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/test/java/org/mitre/oauth2/model/ClientDetailsEntityTest.java b/openid-connect-common/src/test/java/org/mitre/oauth2/model/ClientDetailsEntityTest.java index dbeca24cff..1c4bb28c9e 100644 --- a/openid-connect-common/src/test/java/org/mitre/oauth2/model/ClientDetailsEntityTest.java +++ b/openid-connect-common/src/test/java/org/mitre/oauth2/model/ClientDetailsEntityTest.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/test/java/org/mitre/oauth2/model/RegisteredClientTest.java b/openid-connect-common/src/test/java/org/mitre/oauth2/model/RegisteredClientTest.java index f01d0a604f..c32252eb0f 100644 --- a/openid-connect-common/src/test/java/org/mitre/oauth2/model/RegisteredClientTest.java +++ b/openid-connect-common/src/test/java/org/mitre/oauth2/model/RegisteredClientTest.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/test/java/org/mitre/openid/connect/ClientDetailsEntityJsonProcessorTest.java b/openid-connect-common/src/test/java/org/mitre/openid/connect/ClientDetailsEntityJsonProcessorTest.java index 02a2fd79df..9cd0b8a1d6 100644 --- a/openid-connect-common/src/test/java/org/mitre/openid/connect/ClientDetailsEntityJsonProcessorTest.java +++ b/openid-connect-common/src/test/java/org/mitre/openid/connect/ClientDetailsEntityJsonProcessorTest.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/test/java/org/mitre/openid/connect/config/ConfigurationPropertiesBeanTest.java b/openid-connect-common/src/test/java/org/mitre/openid/connect/config/ConfigurationPropertiesBeanTest.java index 2d0bbca481..97ed3251d6 100644 --- a/openid-connect-common/src/test/java/org/mitre/openid/connect/config/ConfigurationPropertiesBeanTest.java +++ b/openid-connect-common/src/test/java/org/mitre/openid/connect/config/ConfigurationPropertiesBeanTest.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-common/src/test/java/org/mitre/openid/connect/config/ServerConfigurationTest.java b/openid-connect-common/src/test/java/org/mitre/openid/connect/config/ServerConfigurationTest.java index dfbd07da66..4250ac7956 100644 --- a/openid-connect-common/src/test/java/org/mitre/openid/connect/config/ServerConfigurationTest.java +++ b/openid-connect-common/src/test/java/org/mitre/openid/connect/config/ServerConfigurationTest.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index e38161ebc6..24f5e744b4 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -1,20 +1,20 @@ + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> 4.0.0 diff --git a/openid-connect-server-webapp/src/main/resources/log4j.xml b/openid-connect-server-webapp/src/main/resources/log4j.xml index f8289edc91..1daf8ea99c 100644 --- a/openid-connect-server-webapp/src/main/resources/log4j.xml +++ b/openid-connect-server-webapp/src/main/resources/log4j.xml @@ -1,20 +1,20 @@ + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/application-context.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/application-context.xml index d616fa1bf8..d76de13b80 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/application-context.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/application-context.xml @@ -1,20 +1,20 @@ + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> whitelist button on the client management page to create one." } }, - "copyright": "Powered by MITREid Connect {0} © 2015 The MITRE Corporation and MIT KIT..", + "copyright": "Powered by MITREid Connect {0} © 2015 The MITRE Corporation and MIT Internet Trust Consortium..", "about": { "title": "About", - "body": "\nThis OpenID Connect service is built from the MITREid Connect Open Source project, from \nThe MITRE Corporation and the MIT Kerberos and Internet Trust Consortium.\n

\n

\nMore information about the project can be found at \nMITREid Connect on GitHub. \nThere, you can submit bug reports, give feedback, or even contribute code patches for additional features you'd like to see." + "body": "\nThis OpenID Connect service is built from the MITREid Connect Open Source project, from \nThe MITRE Corporation and the MIT Internet Trust Consortium.\n

\n

\nMore information about the project can be found at \nMITREid Connect on GitHub. \nThere, you can submit bug reports, give feedback, or even contribute code patches for additional features you'd like to see." }, "statistics": { "title": "Statistics", diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/locale/sv/messages.json b/openid-connect-server-webapp/src/main/webapp/resources/js/locale/sv/messages.json index 8224e39da9..4258ee6d7a 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/locale/sv/messages.json +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/locale/sv/messages.json @@ -323,10 +323,10 @@ "no-sites": "Det finns inga vitlistade webbplatser. Använd knappen vitlista på klientadminstrationssidan för att skapa en." } }, - "copyright": "Levererat av MITREid Connect {0} © 2015 MITRE Corporation och MIT KIT..", + "copyright": "Levererat av MITREid Connect {0} © 2015 MITRE Corporation och MIT Internet Trust Consortium..", "about": { "title": "Om tjänsten", - "body": "\nDenna OpenID Connect-tjänst är baserad på öppen källkod ifrån projektet MITREid, skapat av \nMITRE Corporation och MIT Kerberos and Internet Trust Consortium.\n

\n

\nMer information om projektet kan finns i projektet \nMITREid Connect på GitHub. \nDär kan du skicka in felrapporter, komma med återkoppling, eller till och med bidra med kodtillägg för ytterligare funktioner du skulle vilja ha." + "body": "\nDenna OpenID Connect-tjänst är baserad på öppen källkod ifrån projektet MITREid, skapat av \nMITRE Corporation och MIT Internet Trust Consortium.\n

\n

\nMer information om projektet kan finns i projektet \nMITREid Connect på GitHub. \nDär kan du skicka in felrapporter, komma med återkoppling, eller till och med bidra med kodtillägg för ytterligare funktioner du skulle vilja ha." }, "statistics": { "title": "Statistik", diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/rsreg.js b/openid-connect-server-webapp/src/main/webapp/resources/js/rsreg.js index b8f95cb8de..79b624880e 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/rsreg.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/rsreg.js @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/scope.js b/openid-connect-server-webapp/src/main/webapp/resources/js/scope.js index c4dcb83df0..1554963fa8 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/scope.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/scope.js @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/token.js b/openid-connect-server-webapp/src/main/webapp/resources/js/token.js index c04a16e092..bfd9f1e953 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/token.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/token.js @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/whitelist.js b/openid-connect-server-webapp/src/main/webapp/resources/js/whitelist.js index 39c0bdd208..dfcd62e2d7 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/whitelist.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/whitelist.js @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/pom.xml b/openid-connect-server/pom.xml index fdbbba4a43..bdea9571fd 100644 --- a/openid-connect-server/pom.xml +++ b/openid-connect-server/pom.xml @@ -1,20 +1,20 @@ + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> 4.0.0 openid-connect-server diff --git a/openid-connect-server/src/main/java/org/mitre/discovery/view/WebfingerView.java b/openid-connect-server/src/main/java/org/mitre/discovery/view/WebfingerView.java index 09de0f044c..a2bc9f2bc2 100644 --- a/openid-connect-server/src/main/java/org/mitre/discovery/view/WebfingerView.java +++ b/openid-connect-server/src/main/java/org/mitre/discovery/view/WebfingerView.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java b/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java index 7b8238c245..8ab27a1425 100644 --- a/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/exception/DuplicateClientIdException.java b/openid-connect-server/src/main/java/org/mitre/oauth2/exception/DuplicateClientIdException.java index 8230b3d0ba..d71df376d3 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/exception/DuplicateClientIdException.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/exception/DuplicateClientIdException.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthenticationHolderRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthenticationHolderRepository.java index b71b578e7b..71912a3e16 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthenticationHolderRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthenticationHolderRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthorizationCodeRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthorizationCodeRepository.java index ac325e589f..3fc0ac9ff4 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthorizationCodeRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthorizationCodeRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2ClientRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2ClientRepository.java index 0cbc4d4c74..915d87c463 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2ClientRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2ClientRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java index 7a23cd5ff2..4171aabe71 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaSystemScopeRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaSystemScopeRepository.java index 20cfa63abf..45a72b28db 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaSystemScopeRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaSystemScopeRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/BlacklistAwareRedirectResolver.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/BlacklistAwareRedirectResolver.java index c8214d2e52..05a08c4fc7 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/BlacklistAwareRedirectResolver.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/BlacklistAwareRedirectResolver.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultIntrospectionResultAssembler.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultIntrospectionResultAssembler.java index 84ec9bea06..8588fa97df 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultIntrospectionResultAssembler.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultIntrospectionResultAssembler.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2AuthorizationCodeService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2AuthorizationCodeService.java index 02062090dc..ab7341d68c 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2AuthorizationCodeService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2AuthorizationCodeService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ClientDetailsEntityService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ClientDetailsEntityService.java index 9e1bf88ee2..60aaf88030 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ClientDetailsEntityService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ClientDetailsEntityService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java index a66eff5d83..e69250dc5a 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultSystemScopeService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultSystemScopeService.java index 9dba8b817a..503cfcbbc8 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultSystemScopeService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultSystemScopeService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/token/ChainedTokenGranter.java b/openid-connect-server/src/main/java/org/mitre/oauth2/token/ChainedTokenGranter.java index 004c77a023..3d17cfa6da 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/token/ChainedTokenGranter.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/token/ChainedTokenGranter.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/token/JWTAssertionTokenGranter.java b/openid-connect-server/src/main/java/org/mitre/oauth2/token/JWTAssertionTokenGranter.java index 69daa536df..45a587335a 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/token/JWTAssertionTokenGranter.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/token/JWTAssertionTokenGranter.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/token/StructuredScopeAwareOAuth2RequestValidator.java b/openid-connect-server/src/main/java/org/mitre/oauth2/token/StructuredScopeAwareOAuth2RequestValidator.java index a66e845753..cb0c79bea0 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/token/StructuredScopeAwareOAuth2RequestValidator.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/token/StructuredScopeAwareOAuth2RequestValidator.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/view/TokenApiView.java b/openid-connect-server/src/main/java/org/mitre/oauth2/view/TokenApiView.java index 98e6ccfcaa..e162051da5 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/view/TokenApiView.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/view/TokenApiView.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/AuthenticationUtilities.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/AuthenticationUtilities.java index 1b220892e5..cfd3c06674 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/AuthenticationUtilities.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/AuthenticationUtilities.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/CorsFilter.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/CorsFilter.java index c79e947ad9..447095f6bb 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/CorsFilter.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/CorsFilter.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/IntrospectionEndpoint.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/IntrospectionEndpoint.java index 3d6147ad64..95da92ccd1 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/IntrospectionEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/IntrospectionEndpoint.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuth2ExceptionHandler.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuth2ExceptionHandler.java index 35efd5c7c8..51c3c8d817 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuth2ExceptionHandler.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuth2ExceptionHandler.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java index b97aa1d6ee..58558a6b30 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/RevocationEndpoint.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/RevocationEndpoint.java index a8d3330689..675231526f 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/RevocationEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/RevocationEndpoint.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/ScopeAPI.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/ScopeAPI.java index 408d45ca00..c870bcd08d 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/ScopeAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/ScopeAPI.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/TokenAPI.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/TokenAPI.java index 567ab7fcb2..dd99edec6e 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/TokenAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/TokenAPI.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAssertionAuthenticationToken.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAssertionAuthenticationToken.java index 383b1e25da..aa58492f97 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAssertionAuthenticationToken.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAssertionAuthenticationToken.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAuthenticationProvider.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAuthenticationProvider.java index 84c0b7e17f..2677cd20a6 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAuthenticationProvider.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAuthenticationProvider.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerClientAssertionTokenEndpointFilter.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerClientAssertionTokenEndpointFilter.java index ccb9064604..1db22a0359 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerClientAssertionTokenEndpointFilter.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerClientAssertionTokenEndpointFilter.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/config/JsonMessageSource.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/config/JsonMessageSource.java index 545df09f72..ee8cf42eaf 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/config/JsonMessageSource.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/config/JsonMessageSource.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/exception/ValidationException.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/exception/ValidationException.java index 5088464ce3..75f2a26561 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/exception/ValidationException.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/exception/ValidationException.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/AuthorizationRequestFilter.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/AuthorizationRequestFilter.java index b538683140..5a8b9a2fdb 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/AuthorizationRequestFilter.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/AuthorizationRequestFilter.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/MultiUrlRequestMatcher.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/MultiUrlRequestMatcher.java index 535bea36a7..a79a21a528 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/MultiUrlRequestMatcher.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/MultiUrlRequestMatcher.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaAddressRepository.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaAddressRepository.java index 8634c1b813..1951315d42 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaAddressRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaAddressRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaApprovedSiteRepository.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaApprovedSiteRepository.java index d0869521d2..2bded680e7 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaApprovedSiteRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaApprovedSiteRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaBlacklistedSiteRepository.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaBlacklistedSiteRepository.java index 53b7fad1ee..bda1c91992 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaBlacklistedSiteRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaBlacklistedSiteRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaPairwiseIdentifierRepository.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaPairwiseIdentifierRepository.java index 2a37a910db..da35c980b6 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaPairwiseIdentifierRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaPairwiseIdentifierRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaUserInfoRepository.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaUserInfoRepository.java index fec468cc6d..bb37efafc0 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaUserInfoRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaUserInfoRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaWhitelistedSiteRepository.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaWhitelistedSiteRepository.java index 0f157befe6..cc0ba5c4a4 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaWhitelistedSiteRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaWhitelistedSiteRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectOAuth2RequestFactory.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectOAuth2RequestFactory.java index 090ae0d9f8..306c7a6f10 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectOAuth2RequestFactory.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectOAuth2RequestFactory.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectRequestParameters.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectRequestParameters.java index 6e38af8fc0..ff23d3f88a 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectRequestParameters.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectRequestParameters.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultApprovedSiteService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultApprovedSiteService.java index 27625f2f5e..8c5d1b907a 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultApprovedSiteService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultApprovedSiteService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultBlacklistedSiteService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultBlacklistedSiteService.java index 16c7bf4f3f..f9941eb6d0 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultBlacklistedSiteService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultBlacklistedSiteService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultOIDCTokenService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultOIDCTokenService.java index c4df09183e..0c865f6785 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultOIDCTokenService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultOIDCTokenService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultScopeClaimTranslationService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultScopeClaimTranslationService.java index 53fddd4d80..9054319203 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultScopeClaimTranslationService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultScopeClaimTranslationService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultStatsService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultStatsService.java index 389e143d1a..8e99b3e367 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultStatsService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultStatsService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultUserInfoService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultUserInfoService.java index 463e9c0949..5ab09c2edc 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultUserInfoService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultUserInfoService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultWhitelistedSiteService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultWhitelistedSiteService.java index d5db58b91e..86774129f9 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultWhitelistedSiteService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultWhitelistedSiteService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DummyResourceSetService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DummyResourceSetService.java index 729d6b59ff..0b93bd07b7 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DummyResourceSetService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DummyResourceSetService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataServiceSupport.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataServiceSupport.java index bdb1cf42f3..43441e0b92 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataServiceSupport.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataServiceSupport.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_0.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_0.java index 6c8a635826..bc9e9098cd 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_0.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_0.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_1.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_1.java index 1e6894f52d..7b852b4766 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_1.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_1.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_2.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_2.java index d628e6002a..e742177d58 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_2.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_2.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MatchLoginHintsAgainstUsers.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MatchLoginHintsAgainstUsers.java index 95a8ae6c1d..848a4439ff 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MatchLoginHintsAgainstUsers.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MatchLoginHintsAgainstUsers.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/PassAllLoginHints.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/PassAllLoginHints.java index 6eb7dfcb9b..cca2ffb4e4 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/PassAllLoginHints.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/PassAllLoginHints.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/RemoveLoginHintsWithHTTP.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/RemoveLoginHintsWithHTTP.java index ba05b06504..d63c660cd0 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/RemoveLoginHintsWithHTTP.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/RemoveLoginHintsWithHTTP.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/UUIDPairwiseIdentiferService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/UUIDPairwiseIdentiferService.java index 6a6796199b..56fc25da59 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/UUIDPairwiseIdentiferService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/UUIDPairwiseIdentiferService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/ConnectTokenEnhancer.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/ConnectTokenEnhancer.java index 6b0cbc80a2..0dbfd9cd5e 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/ConnectTokenEnhancer.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/ConnectTokenEnhancer.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/TofuUserApprovalHandler.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/TofuUserApprovalHandler.java index 11e36a1f20..53e15024a6 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/TofuUserApprovalHandler.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/TofuUserApprovalHandler.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/util/IdTokenHashUtils.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/util/IdTokenHashUtils.java index 3be84b56e2..697b78f501 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/util/IdTokenHashUtils.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/util/IdTokenHashUtils.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/AbstractClientEntityView.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/AbstractClientEntityView.java index f6de571f75..afa5bad9ca 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/AbstractClientEntityView.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/AbstractClientEntityView.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientEntityViewForAdmins.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientEntityViewForAdmins.java index ad6d3d9512..3a24dae78a 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientEntityViewForAdmins.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientEntityViewForAdmins.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientEntityViewForUsers.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientEntityViewForUsers.java index 7e3f05f47c..4fb661e84f 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientEntityViewForUsers.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientEntityViewForUsers.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientInformationResponseView.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientInformationResponseView.java index 10c3c12114..30b73cc416 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientInformationResponseView.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientInformationResponseView.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/HttpCodeView.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/HttpCodeView.java index a6e7850a93..ef3a5188f2 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/HttpCodeView.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/HttpCodeView.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonApprovedSiteView.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonApprovedSiteView.java index 35b866b7b0..d13ad9b86c 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonApprovedSiteView.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonApprovedSiteView.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonEntityView.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonEntityView.java index 58a792692c..0ecce413b6 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonEntityView.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonEntityView.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonErrorView.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonErrorView.java index 520577f505..1c9062b96f 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonErrorView.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonErrorView.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoJWTView.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoJWTView.java index 114263a0ff..41910f63e5 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoJWTView.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoJWTView.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoView.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoView.java index 3ee1e32e84..259b902ce1 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoView.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoView.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ApprovedSiteAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ApprovedSiteAPI.java index 0f71b8a8f9..6ac0397761 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ApprovedSiteAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ApprovedSiteAPI.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/AuthenticationTimeStamper.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/AuthenticationTimeStamper.java index 0bd955a42d..0595a07b55 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/AuthenticationTimeStamper.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/AuthenticationTimeStamper.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/BlacklistAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/BlacklistAPI.java index 39fe23c8ec..0666803311 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/BlacklistAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/BlacklistAPI.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java index 38f18e2c0a..db95245f9e 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DataAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DataAPI.java index 992bd2de4c..2844e695a9 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DataAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DataAPI.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java index 96012cf5eb..e0ac79e96c 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/JWKSetPublishingEndpoint.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/JWKSetPublishingEndpoint.java index b84a8c847e..a4b65fec85 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/JWKSetPublishingEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/JWKSetPublishingEndpoint.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ProtectedResourceRegistrationEndpoint.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ProtectedResourceRegistrationEndpoint.java index 8ae8e81080..77b35c5d25 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ProtectedResourceRegistrationEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ProtectedResourceRegistrationEndpoint.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/RootController.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/RootController.java index eceda9b7e6..1d0ee25815 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/RootController.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/RootController.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ServerConfigInterceptor.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ServerConfigInterceptor.java index 5400f63b06..4fc5180c66 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ServerConfigInterceptor.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ServerConfigInterceptor.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/StatsAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/StatsAPI.java index a1f9b3c7cf..77aaf74879 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/StatsAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/StatsAPI.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/UserInfoEndpoint.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/UserInfoEndpoint.java index e3aa5a838e..7e3b6e5fa1 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/UserInfoEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/UserInfoEndpoint.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/WhitelistAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/WhitelistAPI.java index e951b03e03..ed9a186761 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/WhitelistAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/WhitelistAPI.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestBlacklistAwareRedirectResolver.java b/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestBlacklistAwareRedirectResolver.java index 749de6eda4..e69912b657 100644 --- a/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestBlacklistAwareRedirectResolver.java +++ b/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestBlacklistAwareRedirectResolver.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultIntrospectionResultAssembler.java b/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultIntrospectionResultAssembler.java index 4a13943698..cd8471afd4 100644 --- a/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultIntrospectionResultAssembler.java +++ b/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultIntrospectionResultAssembler.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultOAuth2ClientDetailsEntityService.java b/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultOAuth2ClientDetailsEntityService.java index ff794f61a5..58a845d9a4 100644 --- a/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultOAuth2ClientDetailsEntityService.java +++ b/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultOAuth2ClientDetailsEntityService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultOAuth2ProviderTokenService.java b/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultOAuth2ProviderTokenService.java index 8a8fba0bcd..9c39b3cdf1 100644 --- a/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultOAuth2ProviderTokenService.java +++ b/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultOAuth2ProviderTokenService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultSystemScopeService.java b/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultSystemScopeService.java index d2b4920a35..30e8b452db 100644 --- a/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultSystemScopeService.java +++ b/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultSystemScopeService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultApprovedSiteService.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultApprovedSiteService.java index 95a8049d8e..31c3ec49b4 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultApprovedSiteService.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultApprovedSiteService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultBlacklistedSiteService.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultBlacklistedSiteService.java index 454b536854..0d34fe730b 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultBlacklistedSiteService.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultBlacklistedSiteService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultStatsService.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultStatsService.java index a46890d8d9..24a7ce16b8 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultStatsService.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultStatsService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultUserInfoService.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultUserInfoService.java index 2870eafa10..daae4babe8 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultUserInfoService.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultUserInfoService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultWhitelistedSiteService.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultWhitelistedSiteService.java index dabe482c22..2cd55b58f6 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultWhitelistedSiteService.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultWhitelistedSiteService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_0.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_0.java index 6302afca01..acc3c7e50c 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_0.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_0.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_1.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_1.java index effc1c0ba7..a528ac58e8 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_1.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_1.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_2.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_2.java index e38e9532d1..41354d6b68 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_2.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_2.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestUUIDPairwiseIdentiferService.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestUUIDPairwiseIdentiferService.java index 46fa42c9a2..514f6aa0ea 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestUUIDPairwiseIdentiferService.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestUUIDPairwiseIdentiferService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/util/TestIdTokenHashUtils.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/util/TestIdTokenHashUtils.java index ff8aaf51c0..6819ba295a 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/util/TestIdTokenHashUtils.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/util/TestIdTokenHashUtils.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/pom.xml b/pom.xml index f745e8f9a9..7c81aa1ccb 100644 --- a/pom.xml +++ b/pom.xml @@ -1,20 +1,20 @@ + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> 4.0.0 org.mitre diff --git a/uma-server-webapp/pom.xml b/uma-server-webapp/pom.xml index 8b016c2f77..ce0aa68030 100644 --- a/uma-server-webapp/pom.xml +++ b/uma-server-webapp/pom.xml @@ -1,20 +1,20 @@ + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> 4.0.0 diff --git a/uma-server-webapp/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_2.java b/uma-server-webapp/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_2.java index a0c08c7caf..6ca1b95540 100644 --- a/uma-server-webapp/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_2.java +++ b/uma-server-webapp/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_2.java @@ -1,7 +1,7 @@ package org.mitre.openid.connect.service.impl; /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/uma-server-webapp/src/main/webapp/WEB-INF/application-context.xml b/uma-server-webapp/src/main/webapp/WEB-INF/application-context.xml index c80b2bd92f..02c7db60c9 100644 --- a/uma-server-webapp/src/main/webapp/WEB-INF/application-context.xml +++ b/uma-server-webapp/src/main/webapp/WEB-INF/application-context.xml @@ -1,20 +1,20 @@ + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + Copyright 2015 The MITRE Corporation + and the MIT Internet Trust Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> 4.0.0 diff --git a/uma-server/src/main/java/org/mitre/uma/repository/impl/JpaPermissionRepository.java b/uma-server/src/main/java/org/mitre/uma/repository/impl/JpaPermissionRepository.java index f0adffa4dd..ccd66e0343 100644 --- a/uma-server/src/main/java/org/mitre/uma/repository/impl/JpaPermissionRepository.java +++ b/uma-server/src/main/java/org/mitre/uma/repository/impl/JpaPermissionRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/uma-server/src/main/java/org/mitre/uma/repository/impl/JpaResourceSetRepository.java b/uma-server/src/main/java/org/mitre/uma/repository/impl/JpaResourceSetRepository.java index ffc2bf36d0..f96a9494d0 100644 --- a/uma-server/src/main/java/org/mitre/uma/repository/impl/JpaResourceSetRepository.java +++ b/uma-server/src/main/java/org/mitre/uma/repository/impl/JpaResourceSetRepository.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultPermissionService.java b/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultPermissionService.java index 9adae2f1c3..3bab2efe69 100644 --- a/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultPermissionService.java +++ b/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultPermissionService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultResourceSetService.java b/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultResourceSetService.java index a6d66b87a0..bd162d4293 100644 --- a/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultResourceSetService.java +++ b/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultResourceSetService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultUmaTokenService.java b/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultUmaTokenService.java index 4e2781b9b4..fa55e5dd2e 100644 --- a/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultUmaTokenService.java +++ b/uma-server/src/main/java/org/mitre/uma/service/impl/DefaultUmaTokenService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/uma-server/src/main/java/org/mitre/uma/service/impl/JpaRegisteredClientService.java b/uma-server/src/main/java/org/mitre/uma/service/impl/JpaRegisteredClientService.java index 458a97c455..3cc52b069a 100644 --- a/uma-server/src/main/java/org/mitre/uma/service/impl/JpaRegisteredClientService.java +++ b/uma-server/src/main/java/org/mitre/uma/service/impl/JpaRegisteredClientService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsOnAnyPolicy.java b/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsOnAnyPolicy.java index 9b57cc2938..19a512030b 100644 --- a/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsOnAnyPolicy.java +++ b/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsOnAnyPolicy.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/uma-server/src/main/java/org/mitre/uma/util/ExternalLoginAuthoritiesMapper.java b/uma-server/src/main/java/org/mitre/uma/util/ExternalLoginAuthoritiesMapper.java index 80533aa0ad..f0ffdb35f6 100644 --- a/uma-server/src/main/java/org/mitre/uma/util/ExternalLoginAuthoritiesMapper.java +++ b/uma-server/src/main/java/org/mitre/uma/util/ExternalLoginAuthoritiesMapper.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/uma-server/src/main/java/org/mitre/uma/view/ResourceSetEntityAbbreviatedView.java b/uma-server/src/main/java/org/mitre/uma/view/ResourceSetEntityAbbreviatedView.java index 7f217f90c2..402e27540c 100644 --- a/uma-server/src/main/java/org/mitre/uma/view/ResourceSetEntityAbbreviatedView.java +++ b/uma-server/src/main/java/org/mitre/uma/view/ResourceSetEntityAbbreviatedView.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/uma-server/src/main/java/org/mitre/uma/view/ResourceSetEntityView.java b/uma-server/src/main/java/org/mitre/uma/view/ResourceSetEntityView.java index 7abe83e169..24a3f82bf2 100644 --- a/uma-server/src/main/java/org/mitre/uma/view/ResourceSetEntityView.java +++ b/uma-server/src/main/java/org/mitre/uma/view/ResourceSetEntityView.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java index 7da6b94985..a51053d179 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/uma-server/src/main/java/org/mitre/uma/web/ClaimsCollectionEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/ClaimsCollectionEndpoint.java index b5a376c5ee..1f7916df6c 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/ClaimsCollectionEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/ClaimsCollectionEndpoint.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/uma-server/src/main/java/org/mitre/uma/web/PermissionRegistrationEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/PermissionRegistrationEndpoint.java index d7c19abcd1..a74bbfed25 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/PermissionRegistrationEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/PermissionRegistrationEndpoint.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/uma-server/src/main/java/org/mitre/uma/web/PolicyAPI.java b/uma-server/src/main/java/org/mitre/uma/web/PolicyAPI.java index 545f856889..fc3bb7b1f6 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/PolicyAPI.java +++ b/uma-server/src/main/java/org/mitre/uma/web/PolicyAPI.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java index b68776a4b0..5e1259be64 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/uma-server/src/main/java/org/mitre/uma/web/UmaDiscoveryEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/UmaDiscoveryEndpoint.java index ff44427440..86182bb895 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/UmaDiscoveryEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/UmaDiscoveryEndpoint.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/uma-server/src/main/java/org/mitre/uma/web/UserClaimSearchHelper.java b/uma-server/src/main/java/org/mitre/uma/web/UserClaimSearchHelper.java index 5e61ed17f5..6016046ecb 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/UserClaimSearchHelper.java +++ b/uma-server/src/main/java/org/mitre/uma/web/UserClaimSearchHelper.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/uma-server/src/test/java/org/mitre/uma/service/impl/TestDefaultPermissionService.java b/uma-server/src/test/java/org/mitre/uma/service/impl/TestDefaultPermissionService.java index 2e6ee8100a..f6277121c9 100644 --- a/uma-server/src/test/java/org/mitre/uma/service/impl/TestDefaultPermissionService.java +++ b/uma-server/src/test/java/org/mitre/uma/service/impl/TestDefaultPermissionService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/uma-server/src/test/java/org/mitre/uma/service/impl/TestDefaultResourceSetService.java b/uma-server/src/test/java/org/mitre/uma/service/impl/TestDefaultResourceSetService.java index 60979d5b15..1ebefcee09 100644 --- a/uma-server/src/test/java/org/mitre/uma/service/impl/TestDefaultResourceSetService.java +++ b/uma-server/src/test/java/org/mitre/uma/service/impl/TestDefaultResourceSetService.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2015 The MITRE Corporation - * and the MIT Kerberos and Internet Trust Consortium + * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 616220e048e2b6e41d83f2bbe54b67614d9f894c Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 16 Dec 2015 14:51:27 -0500 Subject: [PATCH 142/465] added praseodym to contributors list (thanks!) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0983ceecf1..742d2ee102 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ The authors and key contributors of the project include: * [Steve Moore](https://github.com/srmoore) * [Mike Derryberry](https://github.com/mtderryberry) * [William Kim](https://github.com/wikkim) +* [Mark Janssen](https://github.com/praseodym) From e1800b5fd6602e3b546191a245c81afbdd03030e Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 16 Dec 2015 14:54:51 -0500 Subject: [PATCH 143/465] fixed ITC URL --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 742d2ee102..3cbfcca79a 100644 --- a/README.md +++ b/README.md @@ -31,4 +31,4 @@ The authors and key contributors of the project include: Copyright ©2015, [The MITRE Corporation](http://www.mitre.org/) - and the [MIT Internet Trust Consortium](http://kit.mit.edu/). Licensed under the Apache 2.0 license, for details see `LICENSE.txt`. + and the [MIT Internet Trust Consortium](http://www.mit-trust.org/). Licensed under the Apache 2.0 license, for details see `LICENSE.txt`. From 698feb49cd54a41a6cb5726c92f2b5fc408b413d Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 16 Dec 2015 22:46:42 -0500 Subject: [PATCH 144/465] check access token expiration on read. closes #983 --- .../impl/DefaultOAuth2ProviderTokenService.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java index e69250dc5a..e2e25016e8 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java @@ -335,15 +335,13 @@ public OAuth2Authentication loadAuthentication(String accessTokenValue) throws A if (accessToken == null) { throw new InvalidTokenException("Invalid access token: " + accessTokenValue); - } - - if (accessToken.isExpired()) { + } else if (accessToken.isExpired()) { //tokenRepository.removeAccessToken(accessToken); revokeAccessToken(accessToken); throw new InvalidTokenException("Expired access token: " + accessTokenValue); + } else { + return accessToken.getAuthenticationHolder().getAuthentication(); } - - return accessToken.getAuthenticationHolder().getAuthentication(); } @@ -355,8 +353,11 @@ public OAuth2AccessTokenEntity readAccessToken(String accessTokenValue) throws A OAuth2AccessTokenEntity accessToken = tokenRepository.getAccessTokenByValue(accessTokenValue); if (accessToken == null) { throw new InvalidTokenException("Access token for value " + accessTokenValue + " was not found"); - } - else { + } else if (accessToken.isExpired()) { + // immediately revoke the expired token + revokeAccessToken(accessToken); + throw new InvalidTokenException("Access token for value " + accessTokenValue + " is expired"); + } else { return accessToken; } } From 105d5d9e3dbdb2bde27cc0899f18b8b4a92f9aff Mon Sep 17 00:00:00 2001 From: Mark Janssen Date: Fri, 18 Dec 2015 15:33:29 +0100 Subject: [PATCH 145/465] Update to Spring 4.1.9 and Spring Security 3.2.9 https://spring.io/blog/2015/12/17/spring-framework-4-2-4-4-1-9-released https://spring.io/blog/2015/11/02/spring-security-3-2-9-released Closes #987 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 7c81aa1ccb..a1bd217d17 100644 --- a/pom.xml +++ b/pom.xml @@ -259,7 +259,7 @@ org.springframework spring-framework-bom - 4.1.8.RELEASE + 4.1.9.RELEASE pom import @@ -280,7 +280,7 @@ org.springframework.security spring-security-bom - 3.2.8.RELEASE + 3.2.9.RELEASE pom import From aa878cc3cf62ecbf056464cd577d4c7f0f9c3501 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 18 Dec 2015 11:22:50 -0500 Subject: [PATCH 146/465] pulled checks for expired tokens into utility functions --- .../DefaultOAuth2ProviderTokenService.java | 67 +++++++++++++------ 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java index e2e25016e8..3fdef5f199 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java @@ -46,6 +46,7 @@ import org.springframework.security.oauth2.common.exceptions.InvalidClientException; import org.springframework.security.oauth2.common.exceptions.InvalidScopeException; import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; +import org.springframework.security.oauth2.provider.ClientAlreadyExistsException; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.TokenRequest; @@ -84,6 +85,10 @@ public class DefaultOAuth2ProviderTokenService implements OAuth2TokenEntityServi @Autowired private SystemScopeService scopeService; + @Autowired + private ApprovedSiteService approvedSiteService; + + @Override public Set getAllAccessTokensForUser(String id) { @@ -91,7 +96,7 @@ public Set getAllAccessTokensForUser(String id) { Set results = Sets.newLinkedHashSet(); for (OAuth2AccessTokenEntity token : all) { - if (token.getAuthenticationHolder().getAuthentication().getName().equals(id)) { + if (clearExpiredAccessToken(token) != null && token.getAuthenticationHolder().getAuthentication().getName().equals(id)) { results.add(token); } } @@ -106,7 +111,7 @@ public Set getAllRefreshTokensForUser(String id) { Set results = Sets.newLinkedHashSet(); for (OAuth2RefreshTokenEntity token : all) { - if (token.getAuthenticationHolder().getAuthentication().getName().equals(id)) { + if (clearExpiredRefreshToken(token) != null && token.getAuthenticationHolder().getAuthentication().getName().equals(id)) { results.add(token); } } @@ -116,18 +121,50 @@ public Set getAllRefreshTokensForUser(String id) { @Override public OAuth2AccessTokenEntity getAccessTokenById(Long id) { - return tokenRepository.getAccessTokenById(id); + return clearExpiredAccessToken(tokenRepository.getAccessTokenById(id)); } @Override public OAuth2RefreshTokenEntity getRefreshTokenById(Long id) { - return tokenRepository.getRefreshTokenById(id); + return clearExpiredRefreshToken(tokenRepository.getRefreshTokenById(id)); } - @Autowired - private ApprovedSiteService approvedSiteService; - - + /** + * Utility function to delete an access token that's expired before returning it. + * @param token the token to check + * @return null if the token is null or expired, the input token (unchanged) if it hasn't + */ + private OAuth2AccessTokenEntity clearExpiredAccessToken(OAuth2AccessTokenEntity token) { + if (token == null) { + return null; + } else if (token.isExpired()) { + // immediately revoke expired token + logger.debug("Clearing expired access token: " + token.getValue()); + revokeAccessToken(token); + return null; + } else { + return token; + } + } + + /** + * Utility function to delete a refresh token that's expired before returning it. + * @param token the token to check + * @return null if the token is null or expired, the input token (unchanged) if it hasn't + */ + private OAuth2RefreshTokenEntity clearExpiredRefreshToken(OAuth2RefreshTokenEntity token) { + if (token == null) { + return null; + } else if (token.isExpired()) { + // immediately revoke expired token + logger.debug("Clearing expired refresh token: " + token.getValue()); + revokeRefreshToken(token); + return null; + } else { + return token; + } + } + @Override public OAuth2AccessTokenEntity createAccessToken(OAuth2Authentication authentication) throws AuthenticationException, InvalidClientException { if (authentication != null && authentication.getOAuth2Request() != null) { @@ -238,7 +275,7 @@ private OAuth2RefreshTokenEntity createRefreshToken(ClientDetailsEntity client, @Override public OAuth2AccessTokenEntity refreshAccessToken(String refreshTokenValue, TokenRequest authRequest) throws AuthenticationException { - OAuth2RefreshTokenEntity refreshToken = tokenRepository.getRefreshTokenByValue(refreshTokenValue); + OAuth2RefreshTokenEntity refreshToken = clearExpiredRefreshToken(tokenRepository.getRefreshTokenByValue(refreshTokenValue)); if (refreshToken == null) { throw new InvalidTokenException("Invalid refresh token: " + refreshTokenValue); @@ -331,14 +368,10 @@ public OAuth2AccessTokenEntity refreshAccessToken(String refreshTokenValue, Toke @Override public OAuth2Authentication loadAuthentication(String accessTokenValue) throws AuthenticationException { - OAuth2AccessTokenEntity accessToken = tokenRepository.getAccessTokenByValue(accessTokenValue); + OAuth2AccessTokenEntity accessToken = clearExpiredAccessToken(tokenRepository.getAccessTokenByValue(accessTokenValue)); if (accessToken == null) { throw new InvalidTokenException("Invalid access token: " + accessTokenValue); - } else if (accessToken.isExpired()) { - //tokenRepository.removeAccessToken(accessToken); - revokeAccessToken(accessToken); - throw new InvalidTokenException("Expired access token: " + accessTokenValue); } else { return accessToken.getAuthenticationHolder().getAuthentication(); } @@ -350,13 +383,9 @@ public OAuth2Authentication loadAuthentication(String accessTokenValue) throws A */ @Override public OAuth2AccessTokenEntity readAccessToken(String accessTokenValue) throws AuthenticationException { - OAuth2AccessTokenEntity accessToken = tokenRepository.getAccessTokenByValue(accessTokenValue); + OAuth2AccessTokenEntity accessToken = clearExpiredAccessToken(tokenRepository.getAccessTokenByValue(accessTokenValue)); if (accessToken == null) { throw new InvalidTokenException("Access token for value " + accessTokenValue + " was not found"); - } else if (accessToken.isExpired()) { - // immediately revoke the expired token - revokeAccessToken(accessToken); - throw new InvalidTokenException("Access token for value " + accessTokenValue + " is expired"); } else { return accessToken; } From d338352cc884ef0b73322daa5e29bac11a890a08 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 18 Dec 2015 15:41:01 -0500 Subject: [PATCH 147/465] scroll Ui to top of page on page loads, closes #977 --- .../src/main/webapp/resources/js/admin.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/admin.js b/openid-connect-server-webapp/src/main/webapp/resources/js/admin.js index efca0a3de3..fc077ecc29 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/admin.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/admin.js @@ -1002,6 +1002,11 @@ $(function () { $.ajaxSetup({cache:false}); app = new AppRouter(); + app.on('route', function(name, args) { + // scroll to top of page on new route selection + $("html, body").animate({ scrollTop: 0 }, "slow"); + }); + // grab all hashed URLs and send them through the app router instead $(document).on('click', 'a[href^="manage/#"]', function(event) { event.preventDefault(); From b3486c31a07b4cdc6baf97d98e2f3f09ea84c931 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 18 Dec 2015 16:30:03 -0500 Subject: [PATCH 148/465] added cache to user info fetcher, closes #833 --- .../connect/client/UserInfoFetcher.java | 150 ++++++++++-------- 1 file changed, 88 insertions(+), 62 deletions(-) diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/UserInfoFetcher.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/UserInfoFetcher.java index edbe6a0edb..a7a78d8566 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/UserInfoFetcher.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/UserInfoFetcher.java @@ -18,6 +18,8 @@ import java.io.IOException; import java.net.URI; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; import org.apache.http.client.HttpClient; import org.apache.http.client.utils.URIBuilder; @@ -37,11 +39,15 @@ import org.springframework.web.client.RestTemplate; import com.google.common.base.Strings; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.util.concurrent.UncheckedExecutionException; import com.google.gson.JsonObject; import com.google.gson.JsonParser; /** - * Utility class to fetch userinfo from the userinfo endpoint, if available. + * Utility class to fetch userinfo from the userinfo endpoint, if available. Caches the results. * @author jricher * */ @@ -52,75 +58,95 @@ public class UserInfoFetcher { */ private static final Logger logger = LoggerFactory.getLogger(UserInfoFetcher.class); + private LoadingCache cache; + + public UserInfoFetcher() { + cache = CacheBuilder.newBuilder() + .expireAfterWrite(1, TimeUnit.HOURS) // expires 1 hour after fetch + .maximumSize(100) + .build(new UserInfoLoader()); + } + public UserInfo loadUserInfo(final PendingOIDCAuthenticationToken token) { - - ServerConfiguration serverConfiguration = token.getServerConfiguration(); - - if (serverConfiguration == null) { - logger.warn("No server configuration found."); - return null; - } - - if (Strings.isNullOrEmpty(serverConfiguration.getUserInfoUri())) { - logger.warn("No userinfo endpoint, not fetching."); + try { + return cache.get(token); + } catch (UncheckedExecutionException | ExecutionException e) { + logger.warn("Couldn't load User Info from token: " + e.getMessage()); return null; } - try { - - // if we got this far, try to actually get the userinfo - HttpClient httpClient = HttpClientBuilder.create() - .useSystemProperties() - .build(); - - HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient); - - String userInfoString = null; - - if (serverConfiguration.getUserInfoTokenMethod() == null || serverConfiguration.getUserInfoTokenMethod().equals(UserInfoTokenMethod.HEADER)) { - RestTemplate restTemplate = new RestTemplate(factory) { - - @Override - protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOException { - ClientHttpRequest httpRequest = super.createRequest(url, method); - httpRequest.getHeaders().add("Authorization", String.format("Bearer %s", token.getAccessTokenValue())); - return httpRequest; - } - }; - - userInfoString = restTemplate.getForObject(serverConfiguration.getUserInfoUri(), String.class); - - } else if (serverConfiguration.getUserInfoTokenMethod().equals(UserInfoTokenMethod.FORM)) { - MultiValueMap form = new LinkedMultiValueMap<>(); - form.add("access_token", token.getAccessTokenValue()); - - RestTemplate restTemplate = new RestTemplate(factory); - userInfoString = restTemplate.postForObject(serverConfiguration.getUserInfoUri(), form, String.class); - } else if (serverConfiguration.getUserInfoTokenMethod().equals(UserInfoTokenMethod.QUERY)) { - URIBuilder builder = new URIBuilder(serverConfiguration.getUserInfoUri()); - builder.setParameter("access_token", token.getAccessTokenValue()); - - RestTemplate restTemplate = new RestTemplate(factory); - userInfoString = restTemplate.getForObject(builder.toString(), String.class); + } + + + private class UserInfoLoader extends CacheLoader { + private HttpClient httpClient = HttpClientBuilder.create() + .useSystemProperties() + .build(); + private HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient); + + public UserInfo load(final PendingOIDCAuthenticationToken token) { + + ServerConfiguration serverConfiguration = token.getServerConfiguration(); + + if (serverConfiguration == null) { + logger.warn("No server configuration found."); + return null; } - - - if (!Strings.isNullOrEmpty(userInfoString)) { - - JsonObject userInfoJson = new JsonParser().parse(userInfoString).getAsJsonObject(); - - UserInfo userInfo = fromJson(userInfoJson); - - return userInfo; - } else { - // didn't get anything, return null + + if (Strings.isNullOrEmpty(serverConfiguration.getUserInfoUri())) { + logger.warn("No userinfo endpoint, not fetching."); return null; } - } catch (Exception e) { - logger.warn("Error fetching userinfo", e); - return null; + + try { + + String userInfoString = null; + + if (serverConfiguration.getUserInfoTokenMethod() == null || serverConfiguration.getUserInfoTokenMethod().equals(UserInfoTokenMethod.HEADER)) { + RestTemplate restTemplate = new RestTemplate(factory) { + + @Override + protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOException { + ClientHttpRequest httpRequest = super.createRequest(url, method); + httpRequest.getHeaders().add("Authorization", String.format("Bearer %s", token.getAccessTokenValue())); + return httpRequest; + } + }; + + userInfoString = restTemplate.getForObject(serverConfiguration.getUserInfoUri(), String.class); + + } else if (serverConfiguration.getUserInfoTokenMethod().equals(UserInfoTokenMethod.FORM)) { + MultiValueMap form = new LinkedMultiValueMap<>(); + form.add("access_token", token.getAccessTokenValue()); + + RestTemplate restTemplate = new RestTemplate(factory); + userInfoString = restTemplate.postForObject(serverConfiguration.getUserInfoUri(), form, String.class); + } else if (serverConfiguration.getUserInfoTokenMethod().equals(UserInfoTokenMethod.QUERY)) { + URIBuilder builder = new URIBuilder(serverConfiguration.getUserInfoUri()); + builder.setParameter("access_token", token.getAccessTokenValue()); + + RestTemplate restTemplate = new RestTemplate(factory); + userInfoString = restTemplate.getForObject(builder.toString(), String.class); + } + + + if (!Strings.isNullOrEmpty(userInfoString)) { + + JsonObject userInfoJson = new JsonParser().parse(userInfoString).getAsJsonObject(); + + UserInfo userInfo = fromJson(userInfoJson); + + return userInfo; + } else { + // didn't get anything, return null + return null; + } + } catch (Exception e) { + logger.warn("Error fetching userinfo", e); + return null; + } + } - } protected UserInfo fromJson(JsonObject userInfoJson) { From 8294dbedd57571cf3c3c81a8870d77e6f645c3ca Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 18 Dec 2015 17:42:15 -0500 Subject: [PATCH 149/465] handled HTTP and parsing errors, fixed guava cache contract, fixes #372 --- .../IntrospectingTokenService.java | 1 + ...egistrationClientConfigurationService.java | 39 ++++++++++++------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/IntrospectingTokenService.java b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/IntrospectingTokenService.java index 2b496217d5..8a232d5f62 100644 --- a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/IntrospectingTokenService.java +++ b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/IntrospectingTokenService.java @@ -298,6 +298,7 @@ protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOE validatedToken = restTemplate.postForObject(introspectionUrl, form, String.class); } catch (RestClientException rce) { logger.error("validateToken", rce); + return null; } if (validatedToken != null) { // parse the json diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/DynamicRegistrationClientConfigurationService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/DynamicRegistrationClientConfigurationService.java index 6b0ca29698..6490ee0dfb 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/DynamicRegistrationClientConfigurationService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/DynamicRegistrationClientConfigurationService.java @@ -39,6 +39,8 @@ import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.security.authentication.AuthenticationServiceException; import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.exceptions.InvalidClientException; +import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; import com.google.common.cache.CacheBuilder; @@ -191,15 +193,18 @@ public RegisteredClient load(ServerConfiguration serverConfig) throws Exception HttpEntity entity = new HttpEntity<>(serializedClient, headers); - String registered = restTemplate.postForObject(serverConfig.getRegistrationEndpointUri(), entity, String.class); - // TODO: handle HTTP errors - - RegisteredClient client = ClientDetailsEntityJsonProcessor.parseRegistered(registered); - - // save this client for later - registeredClientService.save(serverConfig.getIssuer(), client); - - return client; + try { + String registered = restTemplate.postForObject(serverConfig.getRegistrationEndpointUri(), entity, String.class); + + RegisteredClient client = ClientDetailsEntityJsonProcessor.parseRegistered(registered); + + // save this client for later + registeredClientService.save(serverConfig.getIssuer(), client); + + return client; + } catch (RestClientException rce) { + throw new InvalidClientException("Error registering client with server"); + } } else { if (knownClient.getClientId() == null) { @@ -211,12 +216,16 @@ public RegisteredClient load(ServerConfiguration serverConfig) throws Exception HttpEntity entity = new HttpEntity<>(headers); - String registered = restTemplate.exchange(knownClient.getRegistrationClientUri(), HttpMethod.GET, entity, String.class).getBody(); - // TODO: handle HTTP errors - - RegisteredClient client = ClientDetailsEntityJsonProcessor.parseRegistered(registered); - - return client; + try { + String registered = restTemplate.exchange(knownClient.getRegistrationClientUri(), HttpMethod.GET, entity, String.class).getBody(); + // TODO: handle HTTP errors + + RegisteredClient client = ClientDetailsEntityJsonProcessor.parseRegistered(registered); + + return client; + } catch (RestClientException rce) { + throw new InvalidClientException("Error loading previously registered client information from server"); + } } else { // it's got a client ID from the store, don't bother trying to load it return knownClient; From 01ca5ef8e22f45a1737e466c044d32c988a77ebf Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 21 Dec 2015 10:31:47 -0500 Subject: [PATCH 150/465] [maven-release-plugin] prepare release mitreid-connect-1.2.3 --- openid-connect-client/pom.xml | 2 +- openid-connect-common/pom.xml | 2 +- openid-connect-server-webapp/pom.xml | 2 +- openid-connect-server/pom.xml | 2 +- pom.xml | 2 +- uma-server-webapp/pom.xml | 2 +- uma-server/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/openid-connect-client/pom.xml b/openid-connect-client/pom.xml index 162d34ad1d..74ac7adc35 100644 --- a/openid-connect-client/pom.xml +++ b/openid-connect-client/pom.xml @@ -21,7 +21,7 @@ openid-connect-parent org.mitre - 1.2.3-SNAPSHOT + 1.2.3 .. openid-connect-client diff --git a/openid-connect-common/pom.xml b/openid-connect-common/pom.xml index 0f921a523f..9dfb1de741 100644 --- a/openid-connect-common/pom.xml +++ b/openid-connect-common/pom.xml @@ -21,7 +21,7 @@ openid-connect-parent org.mitre - 1.2.3-SNAPSHOT + 1.2.3 .. openid-connect-common diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index 24f5e744b4..e92d25a87d 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.2.3-SNAPSHOT + 1.2.3 openid-connect-server-webapp war diff --git a/openid-connect-server/pom.xml b/openid-connect-server/pom.xml index bdea9571fd..f4b0ffc03e 100644 --- a/openid-connect-server/pom.xml +++ b/openid-connect-server/pom.xml @@ -22,7 +22,7 @@ org.mitre openid-connect-parent - 1.2.3-SNAPSHOT + 1.2.3 .. diff --git a/pom.xml b/pom.xml index a1bd217d17..e42f43feb0 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ 4.0.0 org.mitre openid-connect-parent - 1.2.3-SNAPSHOT + 1.2.3 MITREid Connect pom diff --git a/uma-server-webapp/pom.xml b/uma-server-webapp/pom.xml index ce0aa68030..00222f7c78 100644 --- a/uma-server-webapp/pom.xml +++ b/uma-server-webapp/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.2.3-SNAPSHOT + 1.2.3 .. uma-server-webapp diff --git a/uma-server/pom.xml b/uma-server/pom.xml index d578be5108..480f5d0576 100644 --- a/uma-server/pom.xml +++ b/uma-server/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.2.3-SNAPSHOT + 1.2.3 .. uma-server From e828f3f18d6da75b888878d7c69eec1738a09942 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 21 Dec 2015 10:31:49 -0500 Subject: [PATCH 151/465] [maven-release-plugin] prepare for next development iteration --- openid-connect-client/pom.xml | 2 +- openid-connect-common/pom.xml | 2 +- openid-connect-server-webapp/pom.xml | 2 +- openid-connect-server/pom.xml | 2 +- pom.xml | 2 +- uma-server-webapp/pom.xml | 2 +- uma-server/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/openid-connect-client/pom.xml b/openid-connect-client/pom.xml index 74ac7adc35..73254b9336 100644 --- a/openid-connect-client/pom.xml +++ b/openid-connect-client/pom.xml @@ -21,7 +21,7 @@ openid-connect-parent org.mitre - 1.2.3 + 1.2.4-SNAPSHOT .. openid-connect-client diff --git a/openid-connect-common/pom.xml b/openid-connect-common/pom.xml index 9dfb1de741..1c140a9dcf 100644 --- a/openid-connect-common/pom.xml +++ b/openid-connect-common/pom.xml @@ -21,7 +21,7 @@ openid-connect-parent org.mitre - 1.2.3 + 1.2.4-SNAPSHOT .. openid-connect-common diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index e92d25a87d..15a76ff89f 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.2.3 + 1.2.4-SNAPSHOT openid-connect-server-webapp war diff --git a/openid-connect-server/pom.xml b/openid-connect-server/pom.xml index f4b0ffc03e..a7c1baaaf8 100644 --- a/openid-connect-server/pom.xml +++ b/openid-connect-server/pom.xml @@ -22,7 +22,7 @@ org.mitre openid-connect-parent - 1.2.3 + 1.2.4-SNAPSHOT .. diff --git a/pom.xml b/pom.xml index e42f43feb0..d004c88af4 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ 4.0.0 org.mitre openid-connect-parent - 1.2.3 + 1.2.4-SNAPSHOT MITREid Connect pom diff --git a/uma-server-webapp/pom.xml b/uma-server-webapp/pom.xml index 00222f7c78..543e406e08 100644 --- a/uma-server-webapp/pom.xml +++ b/uma-server-webapp/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.2.3 + 1.2.4-SNAPSHOT .. uma-server-webapp diff --git a/uma-server/pom.xml b/uma-server/pom.xml index 480f5d0576..73ef93df52 100644 --- a/uma-server/pom.xml +++ b/uma-server/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.2.3 + 1.2.4-SNAPSHOT .. uma-server From 099ae41607132b6079083890ab38b15650b30adf Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 21 Dec 2015 14:33:49 -0500 Subject: [PATCH 152/465] added client logo to admin table, closes #280 --- .../webapp/resources/css/mitreid-connect.css | 6 ++++ .../webapp/resources/template/client.html | 33 ++++++++++++------- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/openid-connect-server-webapp/src/main/webapp/resources/css/mitreid-connect.css b/openid-connect-server-webapp/src/main/webapp/resources/css/mitreid-connect.css index 0a67c56a43..9049d5a815 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/css/mitreid-connect.css +++ b/openid-connect-server-webapp/src/main/webapp/resources/css/mitreid-connect.css @@ -186,3 +186,9 @@ h1,label { .user-profile dd, .user-profile dt { height: 20px; } + +/* Client table images */ +.client-logo { + max-width: 64px; + max-height: 64px +} diff --git a/openid-connect-server-webapp/src/main/webapp/resources/template/client.html b/openid-connect-server-webapp/src/main/webapp/resources/template/client.html index 6a61f38c44..5b71f0f6ec 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/template/client.html +++ b/openid-connect-server-webapp/src/main/webapp/resources/template/client.html @@ -28,20 +28,29 @@ -

- <%- client.clientName != null ? client.clientName : ( client.clientId.substr(0,8) + '...' ) %> -
-
- -
-
- <% if (client.dynamicallyRegistered) { %> - - <% } %> - <% if (client.allowIntrospection) { %> - + +
+ <% if (client.logoUri) { %> + <% } %> + +
+ <%- client.clientName != null ? client.clientName : ( client.clientId.substr(0,8) + '...' ) %> +
+
+ +
+
+ <% if (client.dynamicallyRegistered) { %> + + <% } %> + <% if (client.allowIntrospection) { %> + + <% } %> +
+ +
Registered <%- displayCreationDate %>
From 43509b7dfb7c0cbf08429cae9e43ea6d842ae5ff Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 21 Dec 2015 14:37:06 -0500 Subject: [PATCH 153/465] removed a few straggling KIT references --- LICENSE.txt | 2 +- .../src/main/webapp/resources/js/locale/en/messages.json | 2 +- .../src/main/webapp/resources/js/locale/sv/messages.json | 2 +- .../src/main/webapp/resources/template/admin.html | 2 +- .../src/main/webapp/resources/template/blacklist.html | 2 +- .../src/main/webapp/resources/template/client.html | 2 +- .../src/main/webapp/resources/template/dynreg.html | 2 +- .../src/main/webapp/resources/template/grant.html | 2 +- .../src/main/webapp/resources/template/rsreg.html | 2 +- .../src/main/webapp/resources/template/scope.html | 2 +- .../src/main/webapp/resources/template/token.html | 2 +- .../src/main/webapp/resources/template/whitelist.html | 2 +- .../src/main/webapp/resources/template/policy.html | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index a0129ef4b0..dc9aeb4088 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,5 +1,5 @@ Copyright 2015 The MITRE Corporation - and the MIT Kerberos and Internet Trust Consortium + and the MIT Internet Trust Consortium Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json b/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json index 0cf956a682..9e1b1941b6 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json @@ -364,7 +364,7 @@ "more": "More", "about": { "title": "About", - "body": "This OpenID Connect service is built from the MITREid Connect Open Source project, from \nThe MITRE Corporation and the MIT Kerberos and Internet Trust Consortium." + "body": "This OpenID Connect service is built from the MITREid Connect Open Source project, from \nThe MITRE Corporation and the MIT Internet Trust Consortium." }, "contact": { "title": "Contact", diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/locale/sv/messages.json b/openid-connect-server-webapp/src/main/webapp/resources/js/locale/sv/messages.json index 4258ee6d7a..eded1f090a 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/locale/sv/messages.json +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/locale/sv/messages.json @@ -343,7 +343,7 @@ "more": "Mer", "about": { "title": "Om tjänsten", - "body": "\nDenna OpenID Connect-tjänst är byggd från det öpnna källkodsprojektet MITREid, av \nMITRE Corporation och MIT Kerberos and Internet Trust Consortium." + "body": "\nDenna OpenID Connect-tjänst är byggd från det öpnna källkodsprojektet MITREid, av \nMITRE Corporation och MIT Internet Trust Consortium." }, "contact": { "title": "Kontakt", diff --git a/openid-connect-server-webapp/src/main/webapp/resources/template/admin.html b/openid-connect-server-webapp/src/main/webapp/resources/template/admin.html index e36f5e5f3f..2225917f49 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/template/admin.html +++ b/openid-connect-server-webapp/src/main/webapp/resources/template/admin.html @@ -1,6 +1,6 @@ @@ -103,7 +103,7 @@
+ +
+ +
+ +
+

+ + " + + + + + + + "? +

+ + + + + + +   + +
+ + + +
+
+ + diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/deviceApproved.jsp b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/deviceApproved.jsp new file mode 100644 index 0000000000..a31898fe93 --- /dev/null +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/deviceApproved.jsp @@ -0,0 +1,33 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> +<%@ page import="org.springframework.security.core.AuthenticationException"%> +<%@ page import="org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException"%> +<%@ page import="org.springframework.security.web.WebAttributes"%> +<%@ taglib prefix="authz" uri="http://www.springframework.org/security/tags"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%> +<%@ taglib prefix="o" tagdir="/WEB-INF/tags"%> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> + + + + +
+ +
+

+ + + + + + + + +

+ +
+ +
+
+ diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/requestUserCode.jsp b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/requestUserCode.jsp new file mode 100644 index 0000000000..ec80d9b5dd --- /dev/null +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/requestUserCode.jsp @@ -0,0 +1,48 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> +<%@ page import="org.springframework.security.core.AuthenticationException"%> +<%@ page import="org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException"%> +<%@ page import="org.springframework.security.web.WebAttributes"%> +<%@ taglib prefix="authz" uri="http://www.springframework.org/security/tags"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%> +<%@ taglib prefix="o" tagdir="/WEB-INF/tags"%> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> + + + + +
+ +
+

  + + + + + + + + + +

+ +
+ +
+
+ + + + + +   + +
+
+ +
+ +
+
+ diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json b/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json index 1a0c7aed64..99329298ce 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json @@ -487,6 +487,13 @@ "password": "Password", "login-button": "Login", "error": "The system was unable to log you in. Please try again." + }, + "device": { + "request_code": { + "title": "Enter Code", + "header": "Enter code for ", + "description": "Enter the code displayed on your device into the box below and press submit", + "submit": "Submit" + } } - } \ No newline at end of file diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/exception/AuthorizationPendingException.java b/openid-connect-server/src/main/java/org/mitre/oauth2/exception/AuthorizationPendingException.java new file mode 100644 index 0000000000..e2ea2f71b1 --- /dev/null +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/exception/AuthorizationPendingException.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright 2017 The MITRE Corporation + * and the MIT Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +package org.mitre.oauth2.exception; + +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; + +/** + * @author jricher + * + */ +public class AuthorizationPendingException extends OAuth2Exception { + + /** + * @param msg + */ + public AuthorizationPendingException(String msg) { + super(msg); + } + + /** + * + */ + private static final long serialVersionUID = -7078098692596870940L; + + /* (non-Javadoc) + * @see org.springframework.security.oauth2.common.exceptions.OAuth2Exception#getOAuth2ErrorCode() + */ + @Override + public String getOAuth2ErrorCode() { + return "authorization_pending"; + } + + + +} diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/token/DeviceTokenGranter.java b/openid-connect-server/src/main/java/org/mitre/oauth2/token/DeviceTokenGranter.java index 5fd7fbd34c..f8252cab7a 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/token/DeviceTokenGranter.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/token/DeviceTokenGranter.java @@ -17,6 +17,7 @@ package org.mitre.oauth2.token; +import org.mitre.oauth2.exception.AuthorizationPendingException; import org.mitre.oauth2.model.DeviceCode; import org.mitre.oauth2.service.DeviceCodeService; import org.mitre.oauth2.web.DeviceEndpoint; @@ -29,6 +30,7 @@ import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; +import org.springframework.stereotype.Component; /** * Implements https://tools.ietf.org/html/draft-ietf-oauth-device-flow @@ -38,6 +40,7 @@ * @author jricher * */ +@Component("deviceTokenGranter") public class DeviceTokenGranter extends AbstractTokenGranter { public static final String GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code"; @@ -67,12 +70,20 @@ protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, Tok DeviceCode dc = deviceCodeService.consumeDeviceCode(deviceCode, client); if (dc != null) { - // inherit the (approved) scopes from the original request - tokenRequest.setScope(dc.getScope()); - OAuth2Authentication auth = new OAuth2Authentication(getRequestFactory().createOAuth2Request(client, tokenRequest), dc.getAuthenticationHolder().getUserAuth()); + if (dc.isApproved()) { - return auth; + // inherit the (approved) scopes from the original request + tokenRequest.setScope(dc.getScope()); + + OAuth2Authentication auth = new OAuth2Authentication(getRequestFactory().createOAuth2Request(client, tokenRequest), dc.getAuthenticationHolder().getUserAuth()); + + return auth; + } else { + + // still waiting for approval + throw new AuthorizationPendingException("Authorization pending for code " + deviceCode); + } } else { throw new InvalidGrantException("Invalid device code: " + deviceCode); } diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java index 18e83a167e..975f0b0737 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java @@ -23,6 +23,8 @@ import java.util.Set; import java.util.UUID; +import javax.servlet.http.HttpSession; + import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.model.DeviceCode; import org.mitre.oauth2.model.SystemScope; @@ -40,10 +42,15 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.exceptions.InvalidClientException; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.common.util.RandomValueStringGenerator; +import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; @@ -64,7 +71,8 @@ @Controller public class DeviceEndpoint { - public static final String URL = "/device"; + public static final String URL = "device"; + public static final String USER_URL = "device-user"; public static final Logger logger = LoggerFactory.getLogger(DeviceEndpoint.class); @@ -80,9 +88,12 @@ public class DeviceEndpoint { @Autowired private DeviceCodeService deviceCodeService; + @Autowired + private OAuth2RequestFactory oAuth2RequestFactory; + private RandomValueStringGenerator randomGenerator = new RandomValueStringGenerator(); - @RequestMapping(value = URL, method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @RequestMapping(value = "/" + URL, method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public String requestDeviceCode(@RequestParam("client_id") String clientId, @RequestParam(name="scope", required=false) String scope, Map parameters, ModelMap model) { ClientDetailsEntity client; @@ -150,7 +161,7 @@ public String requestDeviceCode(@RequestParam("client_id") String clientId, @Req } @PreAuthorize("hasRole('ROLE_USER')") - @RequestMapping(value = URL, method = RequestMethod.GET) + @RequestMapping(value = "/" + USER_URL, method = RequestMethod.GET) public String requestUserCode(ModelMap model) { // print out a page that asks the user to enter their user code @@ -160,8 +171,8 @@ public String requestUserCode(ModelMap model) { } @PreAuthorize("hasRole('ROLE_USER')") - @RequestMapping(value = URL + "/verify", method = RequestMethod.POST) - public String readUserCode(@RequestParam("userCode") String userCode, ModelMap model) { + @RequestMapping(value = "/" + USER_URL + "/verify", method = RequestMethod.POST) + public String readUserCode(@RequestParam("user_code") String userCode, ModelMap model, HttpSession session) { // look up the request based on the user code DeviceCode dc = deviceCodeService.lookUpByUserCode(userCode); @@ -189,17 +200,30 @@ public String readUserCode(@RequestParam("userCode") String userCode, ModelMap m model.put("scopes", sortedScopes); + AuthorizationRequest authorizationRequest = oAuth2RequestFactory.createAuthorizationRequest(dc.getRequestParameters()); + + session.setAttribute("authorizationRequest", authorizationRequest); + session.setAttribute("deviceCode", dc); + return "approveDevice"; } @PreAuthorize("hasRole('ROLE_USER')") - @RequestMapping(value = URL + "/approve", method = RequestMethod.POST) - public String approveDevice(@RequestParam("userCode") String userCode, @RequestParam(value = "approve", required = false) String approve, ModelMap model) { + @RequestMapping(value = "/" + USER_URL + "/approve", method = RequestMethod.POST) + public String approveDevice(@RequestParam("user_code") String userCode, @RequestParam(value = "user_oauth_approval") String approve, ModelMap model, Authentication auth, HttpSession session) { + AuthorizationRequest authorizationRequest = (AuthorizationRequest) session.getAttribute("authorizationRequest"); + DeviceCode dc = (DeviceCode) session.getAttribute("deviceCode"); - DeviceCode dc = deviceCodeService.lookUpByUserCode(userCode); + if (!dc.getUserCode().equals(userCode)) { + // TODO: return an error + return "error"; + } - DeviceCode approvedCode = deviceCodeService.approveDeviceCode(dc); + OAuth2Request o2req = oAuth2RequestFactory.createOAuth2Request(authorizationRequest); + OAuth2Authentication o2Auth = new OAuth2Authentication(o2req, auth); + + DeviceCode approvedCode = deviceCodeService.approveDeviceCode(dc, o2Auth); ClientDetailsEntity client = clientService.loadClientByClientId(dc.getClientId()); From 9cb5377ce82b4d012e95d4c2ae1cc1abf4da186b Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Sat, 11 Mar 2017 15:28:29 -0500 Subject: [PATCH 341/465] added device code validity seconds to client model --- .../mitre/oauth2/model/ClientDetailsEntity.java | 17 +++++++++++++++++ .../mitre/oauth2/model/RegisteredClient.java | 16 ++++++++++++++++ .../resources/db/hsql/hsql_database_tables.sql | 1 + .../service/impl/MITREidDataService_1_3.java | 4 ++++ 4 files changed, 38 insertions(+) diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/ClientDetailsEntity.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/ClientDetailsEntity.java index 7eb0246972..ed9e511ba1 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/ClientDetailsEntity.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/ClientDetailsEntity.java @@ -145,6 +145,7 @@ public class ClientDetailsEntity implements ClientDetails { private Integer idTokenValiditySeconds; //timeout for id tokens private Date createdAt; // time the client was created private boolean clearAccessTokensOnRefresh = true; // do we clear access tokens on refresh? + private Integer deviceCodeValiditySeconds; // timeout for device codes /** fields for UMA */ private Set claimsRedirectUris; @@ -1032,4 +1033,20 @@ public void setCodeChallengeMethod(PKCEAlgorithm codeChallengeMethod) { this.codeChallengeMethod = codeChallengeMethod; } + /** + * @return the deviceCodeValiditySeconds + */ + @Basic + @Column(name="device_code_validity_seconds") + public Integer getDeviceCodeValiditySeconds() { + return deviceCodeValiditySeconds; + } + + /** + * @param deviceCodeValiditySeconds the deviceCodeValiditySeconds to set + */ + public void setDeviceCodeValiditySeconds(Integer deviceCodeValiditySeconds) { + this.deviceCodeValiditySeconds = deviceCodeValiditySeconds; + } + } diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClient.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClient.java index a0e8a9312c..f5e195899d 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClient.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClient.java @@ -846,6 +846,22 @@ public void setSource(JsonObject src) { this.src = src; } + /** + * @return + * @see org.mitre.oauth2.model.ClientDetailsEntity#getDeviceCodeValiditySeconds() + */ + public Integer getDeviceCodeValiditySeconds() { + return client.getDeviceCodeValiditySeconds(); + } + + /** + * @param deviceCodeValiditySeconds + * @see org.mitre.oauth2.model.ClientDetailsEntity#setDeviceCodeValiditySeconds(java.lang.Integer) + */ + public void setDeviceCodeValiditySeconds(Integer deviceCodeValiditySeconds) { + client.setDeviceCodeValiditySeconds(deviceCodeValiditySeconds); + } + } diff --git a/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql b/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql index 23493f0eae..bf8e827f91 100644 --- a/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql +++ b/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql @@ -131,6 +131,7 @@ CREATE TABLE IF NOT EXISTS client_details ( dynamically_registered BOOLEAN DEFAULT false NOT NULL, allow_introspection BOOLEAN DEFAULT false NOT NULL, id_token_validity_seconds BIGINT DEFAULT 600 NOT NULL, + device_code_validity_seconds BIGINT DEFAULT 600 NOT NULL, client_id VARCHAR(256), client_secret VARCHAR(2048), diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_3.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_3.java index 6ce0f94811..be2fb65f1e 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_3.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_3.java @@ -117,6 +117,7 @@ public class MITREidDataService_1_3 extends MITREidDataServiceSupport implements private static final String REFRESH_TOKEN_VALIDITY_SECONDS = "refreshTokenValiditySeconds"; private static final String ACCESS_TOKEN_VALIDITY_SECONDS = "accessTokenValiditySeconds"; private static final String ID_TOKEN_VALIDITY_SECONDS = "idTokenValiditySeconds"; + private static final String DEVICE_CODE_VALIDITY_SECONDS = "deviceCodeValiditySeconds"; private static final String SECRET = "secret"; private static final String URI = "uri"; private static final String CREATOR_USER_ID = "creatorUserId"; @@ -452,6 +453,7 @@ private void writeClients(JsonWriter writer) { writer.name(ACCESS_TOKEN_VALIDITY_SECONDS).value(client.getAccessTokenValiditySeconds()); writer.name(REFRESH_TOKEN_VALIDITY_SECONDS).value(client.getRefreshTokenValiditySeconds()); writer.name(ID_TOKEN_VALIDITY_SECONDS).value(client.getIdTokenValiditySeconds()); + writer.name(DEVICE_CODE_VALIDITY_SECONDS).value(client.getDeviceCodeValiditySeconds()); writer.name(REDIRECT_URIS); writeNullSafeArray(writer, client.getRedirectUris()); writer.name(CLAIMS_REDIRECT_URIS); @@ -1056,6 +1058,8 @@ private void readClients(JsonReader reader) throws IOException { client.setRefreshTokenValiditySeconds(reader.nextInt()); } else if (name.equals(ID_TOKEN_VALIDITY_SECONDS)) { client.setIdTokenValiditySeconds(reader.nextInt()); + } else if (name.equals(DEVICE_CODE_VALIDITY_SECONDS)) { + client.setDeviceCodeValiditySeconds(reader.nextInt()); } else if (name.equals(REDIRECT_URIS)) { Set redirectUris = readSet(reader); client.setRedirectUris(redirectUris); From 548dad4e2958a4e56b29572b4c733abfdf17e780 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Sat, 11 Mar 2017 15:29:08 -0500 Subject: [PATCH 342/465] added expiration to device codes --- .../org/mitre/oauth2/model/DeviceCode.java | 15 +- .../oauth2/service/DeviceCodeService.java | 19 +- .../bootstrap2/css/bootstrap-responsive.css | 1089 ++++ .../resources/bootstrap2/css/bootstrap.css | 5236 +++++++++++++++++ .../exception/DeviceCodeExpiredException.java | 48 + .../impl/InMemoryDeviceCodeService.java | 102 + .../oauth2/token/DeviceTokenGranter.java | 18 +- .../org/mitre/oauth2/web/DeviceEndpoint.java | 45 +- 8 files changed, 6554 insertions(+), 18 deletions(-) create mode 100644 openid-connect-server-webapp/src/main/webapp/resources/bootstrap2/css/bootstrap-responsive.css create mode 100644 openid-connect-server-webapp/src/main/webapp/resources/bootstrap2/css/bootstrap.css create mode 100644 openid-connect-server/src/main/java/org/mitre/oauth2/exception/DeviceCodeExpiredException.java create mode 100644 openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/InMemoryDeviceCodeService.java diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/DeviceCode.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/DeviceCode.java index 9f7fa8eba7..8f7486b9fe 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/DeviceCode.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/DeviceCode.java @@ -17,6 +17,7 @@ package org.mitre.oauth2.model; +import java.util.Date; import java.util.Map; import java.util.Set; @@ -33,6 +34,7 @@ import javax.persistence.ManyToOne; import javax.persistence.MapKeyColumn; import javax.persistence.Table; +import javax.persistence.Temporal; /** * @author jricher @@ -46,6 +48,7 @@ public class DeviceCode { private String deviceCode; private String userCode; private Set scope; + private Date expiration; private String clientId; private Map requestParameters; private boolean approved; @@ -61,7 +64,6 @@ public DeviceCode(String deviceCode, String userCode, Set scope, String this.scope = scope; this.clientId = clientId; this.requestParameters = params; - this.setApproved(false); } /** @@ -133,6 +135,17 @@ public void setScope(Set scope) { this.scope = scope; } + @Basic + @Temporal(javax.persistence.TemporalType.TIMESTAMP) + @Column(name = "expiration") + public Date getExpiration() { + return expiration; + } + + public void setExpiration(Date expiration) { + this.expiration = expiration; + } + /** * @return the clientId */ diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java b/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java index 443bb674bf..6d5810e204 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java @@ -17,6 +17,10 @@ package org.mitre.oauth2.service; +import java.util.Map; +import java.util.Set; + +import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.model.DeviceCode; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.OAuth2Authentication; @@ -28,11 +32,6 @@ */ public interface DeviceCodeService { - /** - * @param dc - */ - public DeviceCode save(DeviceCode dc); - /** * @param userCode * @return @@ -52,4 +51,14 @@ public interface DeviceCodeService { */ public DeviceCode consumeDeviceCode(String deviceCode, ClientDetails client); + /** + * @param deviceCode + * @param userCode + * @param requestedScopes + * @param client + * @param parameters + * @return + */ + public DeviceCode createNewDeviceCode(String deviceCode, String userCode, Set requestedScopes, ClientDetailsEntity client, Map parameters); + } diff --git a/openid-connect-server-webapp/src/main/webapp/resources/bootstrap2/css/bootstrap-responsive.css b/openid-connect-server-webapp/src/main/webapp/resources/bootstrap2/css/bootstrap-responsive.css new file mode 100644 index 0000000000..ac63813ee1 --- /dev/null +++ b/openid-connect-server-webapp/src/main/webapp/resources/bootstrap2/css/bootstrap-responsive.css @@ -0,0 +1,1089 @@ +/*! + * Bootstrap Responsive v2.3.2 + * + * Copyright 2013 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world by @mdo and @fat. + */ +.clearfix { + *zoom: 1; +} +.clearfix:before, +.clearfix:after { + display: table; + content: ""; + line-height: 0; +} +.clearfix:after { + clear: both; +} +.hide-text { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.input-block-level { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +@-ms-viewport { + width: device-width; +} +.hidden { + display: none; + visibility: hidden; +} +.visible-phone { + display: none !important; +} +.visible-tablet { + display: none !important; +} +.hidden-desktop { + display: none !important; +} +.visible-desktop { + display: inherit !important; +} +@media (min-width: 768px) and (max-width: 979px) { + .hidden-desktop { + display: inherit !important; + } + .visible-desktop { + display: none !important ; + } + .visible-tablet { + display: inherit !important; + } + .hidden-tablet { + display: none !important; + } +} +@media (max-width: 767px) { + .hidden-desktop { + display: inherit !important; + } + .visible-desktop { + display: none !important; + } + .visible-phone { + display: inherit !important; + } + .hidden-phone { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: inherit !important; + } + .hidden-print { + display: none !important; + } +} +@media (min-width: 1200px) { + .row { + margin-left: -30px; + *zoom: 1; + } + .row:before, + .row:after { + display: table; + content: ""; + line-height: 0; + } + .row:after { + clear: both; + } + [class*="span"] { + float: left; + min-height: 1px; + margin-left: 30px; + } + .container, + .navbar-static-top .container, + .navbar-fixed-top .container, + .navbar-fixed-bottom .container { + width: 1170px; + } + .span12 { + width: 1170px; + } + .span11 { + width: 1070px; + } + .span10 { + width: 970px; + } + .span9 { + width: 870px; + } + .span8 { + width: 770px; + } + .span7 { + width: 670px; + } + .span6 { + width: 570px; + } + .span5 { + width: 470px; + } + .span4 { + width: 370px; + } + .span3 { + width: 270px; + } + .span2 { + width: 170px; + } + .span1 { + width: 70px; + } + .offset12 { + margin-left: 1230px; + } + .offset11 { + margin-left: 1130px; + } + .offset10 { + margin-left: 1030px; + } + .offset9 { + margin-left: 930px; + } + .offset8 { + margin-left: 830px; + } + .offset7 { + margin-left: 730px; + } + .offset6 { + margin-left: 630px; + } + .offset5 { + margin-left: 530px; + } + .offset4 { + margin-left: 430px; + } + .offset3 { + margin-left: 330px; + } + .offset2 { + margin-left: 230px; + } + .offset1 { + margin-left: 130px; + } + .row-fluid { + width: 100%; + *zoom: 1; + } + .row-fluid:before, + .row-fluid:after { + display: table; + content: ""; + line-height: 0; + } + .row-fluid:after { + clear: both; + } + .row-fluid [class*="span"] { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + float: left; + margin-left: 2.56410256%; + *margin-left: 2.51091107%; + } + .row-fluid [class*="span"]:first-child { + margin-left: 0; + } + .row-fluid .controls-row [class*="span"] + [class*="span"] { + margin-left: 2.56410256%; + } + .row-fluid .span12 { + width: 100%; + *width: 99.94680851%; + } + .row-fluid .span11 { + width: 91.45299145%; + *width: 91.39979996%; + } + .row-fluid .span10 { + width: 82.90598291%; + *width: 82.85279142%; + } + .row-fluid .span9 { + width: 74.35897436%; + *width: 74.30578287%; + } + .row-fluid .span8 { + width: 65.81196581%; + *width: 65.75877432%; + } + .row-fluid .span7 { + width: 57.26495726%; + *width: 57.21176578%; + } + .row-fluid .span6 { + width: 48.71794872%; + *width: 48.66475723%; + } + .row-fluid .span5 { + width: 40.17094017%; + *width: 40.11774868%; + } + .row-fluid .span4 { + width: 31.62393162%; + *width: 31.57074013%; + } + .row-fluid .span3 { + width: 23.07692308%; + *width: 23.02373159%; + } + .row-fluid .span2 { + width: 14.52991453%; + *width: 14.47672304%; + } + .row-fluid .span1 { + width: 5.98290598%; + *width: 5.92971449%; + } + .row-fluid .offset12 { + margin-left: 105.12820513%; + *margin-left: 105.02182215%; + } + .row-fluid .offset12:first-child { + margin-left: 102.56410256%; + *margin-left: 102.45771959%; + } + .row-fluid .offset11 { + margin-left: 96.58119658%; + *margin-left: 96.4748136%; + } + .row-fluid .offset11:first-child { + margin-left: 94.01709402%; + *margin-left: 93.91071104%; + } + .row-fluid .offset10 { + margin-left: 88.03418803%; + *margin-left: 87.92780506%; + } + .row-fluid .offset10:first-child { + margin-left: 85.47008547%; + *margin-left: 85.36370249%; + } + .row-fluid .offset9 { + margin-left: 79.48717949%; + *margin-left: 79.38079651%; + } + .row-fluid .offset9:first-child { + margin-left: 76.92307692%; + *margin-left: 76.81669394%; + } + .row-fluid .offset8 { + margin-left: 70.94017094%; + *margin-left: 70.83378796%; + } + .row-fluid .offset8:first-child { + margin-left: 68.37606838%; + *margin-left: 68.2696854%; + } + .row-fluid .offset7 { + margin-left: 62.39316239%; + *margin-left: 62.28677941%; + } + .row-fluid .offset7:first-child { + margin-left: 59.82905983%; + *margin-left: 59.72267685%; + } + .row-fluid .offset6 { + margin-left: 53.84615385%; + *margin-left: 53.73977087%; + } + .row-fluid .offset6:first-child { + margin-left: 51.28205128%; + *margin-left: 51.1756683%; + } + .row-fluid .offset5 { + margin-left: 45.2991453%; + *margin-left: 45.19276232%; + } + .row-fluid .offset5:first-child { + margin-left: 42.73504274%; + *margin-left: 42.62865976%; + } + .row-fluid .offset4 { + margin-left: 36.75213675%; + *margin-left: 36.64575377%; + } + .row-fluid .offset4:first-child { + margin-left: 34.18803419%; + *margin-left: 34.08165121%; + } + .row-fluid .offset3 { + margin-left: 28.20512821%; + *margin-left: 28.09874523%; + } + .row-fluid .offset3:first-child { + margin-left: 25.64102564%; + *margin-left: 25.53464266%; + } + .row-fluid .offset2 { + margin-left: 19.65811966%; + *margin-left: 19.55173668%; + } + .row-fluid .offset2:first-child { + margin-left: 17.09401709%; + *margin-left: 16.98763412%; + } + .row-fluid .offset1 { + margin-left: 11.11111111%; + *margin-left: 11.00472813%; + } + .row-fluid .offset1:first-child { + margin-left: 8.54700855%; + *margin-left: 8.44062557%; + } + input, + textarea, + .uneditable-input { + margin-left: 0; + } + .controls-row [class*="span"] + [class*="span"] { + margin-left: 30px; + } + input.span12, + textarea.span12, + .uneditable-input.span12 { + width: 1156px; + } + input.span11, + textarea.span11, + .uneditable-input.span11 { + width: 1056px; + } + input.span10, + textarea.span10, + .uneditable-input.span10 { + width: 956px; + } + input.span9, + textarea.span9, + .uneditable-input.span9 { + width: 856px; + } + input.span8, + textarea.span8, + .uneditable-input.span8 { + width: 756px; + } + input.span7, + textarea.span7, + .uneditable-input.span7 { + width: 656px; + } + input.span6, + textarea.span6, + .uneditable-input.span6 { + width: 556px; + } + input.span5, + textarea.span5, + .uneditable-input.span5 { + width: 456px; + } + input.span4, + textarea.span4, + .uneditable-input.span4 { + width: 356px; + } + input.span3, + textarea.span3, + .uneditable-input.span3 { + width: 256px; + } + input.span2, + textarea.span2, + .uneditable-input.span2 { + width: 156px; + } + input.span1, + textarea.span1, + .uneditable-input.span1 { + width: 56px; + } + .thumbnails { + margin-left: -30px; + } + .thumbnails > li { + margin-left: 30px; + } + .row-fluid .thumbnails { + margin-left: 0; + } +} +@media (min-width: 768px) and (max-width: 979px) { + .row { + margin-left: -20px; + *zoom: 1; + } + .row:before, + .row:after { + display: table; + content: ""; + line-height: 0; + } + .row:after { + clear: both; + } + [class*="span"] { + float: left; + min-height: 1px; + margin-left: 20px; + } + .container, + .navbar-static-top .container, + .navbar-fixed-top .container, + .navbar-fixed-bottom .container { + width: 724px; + } + .span12 { + width: 724px; + } + .span11 { + width: 662px; + } + .span10 { + width: 600px; + } + .span9 { + width: 538px; + } + .span8 { + width: 476px; + } + .span7 { + width: 414px; + } + .span6 { + width: 352px; + } + .span5 { + width: 290px; + } + .span4 { + width: 228px; + } + .span3 { + width: 166px; + } + .span2 { + width: 104px; + } + .span1 { + width: 42px; + } + .offset12 { + margin-left: 764px; + } + .offset11 { + margin-left: 702px; + } + .offset10 { + margin-left: 640px; + } + .offset9 { + margin-left: 578px; + } + .offset8 { + margin-left: 516px; + } + .offset7 { + margin-left: 454px; + } + .offset6 { + margin-left: 392px; + } + .offset5 { + margin-left: 330px; + } + .offset4 { + margin-left: 268px; + } + .offset3 { + margin-left: 206px; + } + .offset2 { + margin-left: 144px; + } + .offset1 { + margin-left: 82px; + } + .row-fluid { + width: 100%; + *zoom: 1; + } + .row-fluid:before, + .row-fluid:after { + display: table; + content: ""; + line-height: 0; + } + .row-fluid:after { + clear: both; + } + .row-fluid [class*="span"] { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + float: left; + margin-left: 2.76243094%; + *margin-left: 2.70923945%; + } + .row-fluid [class*="span"]:first-child { + margin-left: 0; + } + .row-fluid .controls-row [class*="span"] + [class*="span"] { + margin-left: 2.76243094%; + } + .row-fluid .span12 { + width: 100%; + *width: 99.94680851%; + } + .row-fluid .span11 { + width: 91.43646409%; + *width: 91.3832726%; + } + .row-fluid .span10 { + width: 82.87292818%; + *width: 82.81973669%; + } + .row-fluid .span9 { + width: 74.30939227%; + *width: 74.25620078%; + } + .row-fluid .span8 { + width: 65.74585635%; + *width: 65.69266486%; + } + .row-fluid .span7 { + width: 57.18232044%; + *width: 57.12912895%; + } + .row-fluid .span6 { + width: 48.61878453%; + *width: 48.56559304%; + } + .row-fluid .span5 { + width: 40.05524862%; + *width: 40.00205713%; + } + .row-fluid .span4 { + width: 31.49171271%; + *width: 31.43852122%; + } + .row-fluid .span3 { + width: 22.9281768%; + *width: 22.87498531%; + } + .row-fluid .span2 { + width: 14.36464088%; + *width: 14.31144939%; + } + .row-fluid .span1 { + width: 5.80110497%; + *width: 5.74791348%; + } + .row-fluid .offset12 { + margin-left: 105.52486188%; + *margin-left: 105.4184789%; + } + .row-fluid .offset12:first-child { + margin-left: 102.76243094%; + *margin-left: 102.65604796%; + } + .row-fluid .offset11 { + margin-left: 96.96132597%; + *margin-left: 96.85494299%; + } + .row-fluid .offset11:first-child { + margin-left: 94.19889503%; + *margin-left: 94.09251205%; + } + .row-fluid .offset10 { + margin-left: 88.39779006%; + *margin-left: 88.29140708%; + } + .row-fluid .offset10:first-child { + margin-left: 85.63535912%; + *margin-left: 85.52897614%; + } + .row-fluid .offset9 { + margin-left: 79.83425414%; + *margin-left: 79.72787116%; + } + .row-fluid .offset9:first-child { + margin-left: 77.0718232%; + *margin-left: 76.96544023%; + } + .row-fluid .offset8 { + margin-left: 71.27071823%; + *margin-left: 71.16433525%; + } + .row-fluid .offset8:first-child { + margin-left: 68.50828729%; + *margin-left: 68.40190431%; + } + .row-fluid .offset7 { + margin-left: 62.70718232%; + *margin-left: 62.60079934%; + } + .row-fluid .offset7:first-child { + margin-left: 59.94475138%; + *margin-left: 59.8383684%; + } + .row-fluid .offset6 { + margin-left: 54.14364641%; + *margin-left: 54.03726343%; + } + .row-fluid .offset6:first-child { + margin-left: 51.38121547%; + *margin-left: 51.27483249%; + } + .row-fluid .offset5 { + margin-left: 45.5801105%; + *margin-left: 45.47372752%; + } + .row-fluid .offset5:first-child { + margin-left: 42.81767956%; + *margin-left: 42.71129658%; + } + .row-fluid .offset4 { + margin-left: 37.01657459%; + *margin-left: 36.91019161%; + } + .row-fluid .offset4:first-child { + margin-left: 34.25414365%; + *margin-left: 34.14776067%; + } + .row-fluid .offset3 { + margin-left: 28.45303867%; + *margin-left: 28.3466557%; + } + .row-fluid .offset3:first-child { + margin-left: 25.69060773%; + *margin-left: 25.58422476%; + } + .row-fluid .offset2 { + margin-left: 19.88950276%; + *margin-left: 19.78311978%; + } + .row-fluid .offset2:first-child { + margin-left: 17.12707182%; + *margin-left: 17.02068884%; + } + .row-fluid .offset1 { + margin-left: 11.32596685%; + *margin-left: 11.21958387%; + } + .row-fluid .offset1:first-child { + margin-left: 8.56353591%; + *margin-left: 8.45715293%; + } + input, + textarea, + .uneditable-input { + margin-left: 0; + } + .controls-row [class*="span"] + [class*="span"] { + margin-left: 20px; + } + input.span12, + textarea.span12, + .uneditable-input.span12 { + width: 710px; + } + input.span11, + textarea.span11, + .uneditable-input.span11 { + width: 648px; + } + input.span10, + textarea.span10, + .uneditable-input.span10 { + width: 586px; + } + input.span9, + textarea.span9, + .uneditable-input.span9 { + width: 524px; + } + input.span8, + textarea.span8, + .uneditable-input.span8 { + width: 462px; + } + input.span7, + textarea.span7, + .uneditable-input.span7 { + width: 400px; + } + input.span6, + textarea.span6, + .uneditable-input.span6 { + width: 338px; + } + input.span5, + textarea.span5, + .uneditable-input.span5 { + width: 276px; + } + input.span4, + textarea.span4, + .uneditable-input.span4 { + width: 214px; + } + input.span3, + textarea.span3, + .uneditable-input.span3 { + width: 152px; + } + input.span2, + textarea.span2, + .uneditable-input.span2 { + width: 90px; + } + input.span1, + textarea.span1, + .uneditable-input.span1 { + width: 28px; + } +} +@media (max-width: 767px) { + body { + padding-left: 20px; + padding-right: 20px; + } + .navbar-fixed-top, + .navbar-fixed-bottom, + .navbar-static-top { + margin-left: -20px; + margin-right: -20px; + } + .container-fluid { + padding: 0; + } + .dl-horizontal dt { + float: none; + clear: none; + width: auto; + text-align: left; + } + .dl-horizontal dd { + margin-left: 0; + } + .container { + width: auto; + } + .row-fluid { + width: 100%; + } + .row, + .thumbnails { + margin-left: 0; + } + .thumbnails > li { + float: none; + margin-left: 0; + } + [class*="span"], + .uneditable-input[class*="span"], + .row-fluid [class*="span"] { + float: none; + display: block; + width: 100%; + margin-left: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .span12, + .row-fluid .span12 { + width: 100%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .row-fluid [class*="offset"]:first-child { + margin-left: 0; + } + .input-large, + .input-xlarge, + .input-xxlarge, + input[class*="span"], + select[class*="span"], + textarea[class*="span"], + .uneditable-input { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .input-prepend input, + .input-append input, + .input-prepend input[class*="span"], + .input-append input[class*="span"] { + display: inline-block; + width: auto; + } + .controls-row [class*="span"] + [class*="span"] { + margin-left: 0; + } + .modal { + position: fixed; + top: 20px; + left: 20px; + right: 20px; + width: auto; + margin: 0; + } + .modal.fade { + top: -100px; + } + .modal.fade.in { + top: 20px; + } +} +@media (max-width: 480px) { + .nav-collapse { + -webkit-transform: translate3d(0, 0, 0); + } + .page-header h1 small { + display: block; + line-height: 20px; + } + input[type="checkbox"], + input[type="radio"] { + border: 1px solid #ccc; + } + .form-horizontal .control-label { + float: none; + width: auto; + padding-top: 0; + text-align: left; + } + .form-horizontal .controls { + margin-left: 0; + } + .form-horizontal .control-list { + padding-top: 0; + } + .form-horizontal .form-actions { + padding-left: 10px; + padding-right: 10px; + } + .media .pull-left, + .media .pull-right { + float: none; + display: block; + margin-bottom: 10px; + } + .media-object { + margin-right: 0; + margin-left: 0; + } + .modal { + top: 10px; + left: 10px; + right: 10px; + } + .modal-header .close { + padding: 10px; + margin: -10px; + } + .carousel-caption { + position: static; + } +} +@media (max-width: 979px) { + body { + padding-top: 0; + } + .navbar-fixed-top, + .navbar-fixed-bottom { + position: static; + } + .navbar-fixed-top { + margin-bottom: 20px; + } + .navbar-fixed-bottom { + margin-top: 20px; + } + .navbar-fixed-top .navbar-inner, + .navbar-fixed-bottom .navbar-inner { + padding: 5px; + } + .navbar .container { + width: auto; + padding: 0; + } + .navbar .brand { + padding-left: 10px; + padding-right: 10px; + margin: 0 0 0 -5px; + } + .nav-collapse { + clear: both; + } + .nav-collapse .nav { + float: none; + margin: 0 0 10px; + } + .nav-collapse .nav > li { + float: none; + } + .nav-collapse .nav > li > a { + margin-bottom: 2px; + } + .nav-collapse .nav > .divider-vertical { + display: none; + } + .nav-collapse .nav .nav-header { + color: #777777; + text-shadow: none; + } + .nav-collapse .nav > li > a, + .nav-collapse .dropdown-menu a { + padding: 9px 15px; + font-weight: bold; + color: #777777; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + } + .nav-collapse .btn { + padding: 4px 10px 4px; + font-weight: normal; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + } + .nav-collapse .dropdown-menu li + li a { + margin-bottom: 2px; + } + .nav-collapse .nav > li > a:hover, + .nav-collapse .nav > li > a:focus, + .nav-collapse .dropdown-menu a:hover, + .nav-collapse .dropdown-menu a:focus { + background-color: #f2f2f2; + } + .navbar-inverse .nav-collapse .nav > li > a, + .navbar-inverse .nav-collapse .dropdown-menu a { + color: #999999; + } + .navbar-inverse .nav-collapse .nav > li > a:hover, + .navbar-inverse .nav-collapse .nav > li > a:focus, + .navbar-inverse .nav-collapse .dropdown-menu a:hover, + .navbar-inverse .nav-collapse .dropdown-menu a:focus { + background-color: #111111; + } + .nav-collapse.in .btn-group { + margin-top: 5px; + padding: 0; + } + .nav-collapse .dropdown-menu { + position: static; + top: auto; + left: auto; + float: none; + display: none; + max-width: none; + margin: 0 15px; + padding: 0; + background-color: transparent; + border: none; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + } + .nav-collapse .open > .dropdown-menu { + display: block; + } + .nav-collapse .dropdown-menu:before, + .nav-collapse .dropdown-menu:after { + display: none; + } + .nav-collapse .dropdown-menu .divider { + display: none; + } + .nav-collapse .nav > li > .dropdown-menu:before, + .nav-collapse .nav > li > .dropdown-menu:after { + display: none; + } + .nav-collapse .navbar-form, + .nav-collapse .navbar-search { + float: none; + padding: 10px 15px; + margin: 10px 0; + border-top: 1px solid #f2f2f2; + border-bottom: 1px solid #f2f2f2; + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1); + -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1); + box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1); + } + .navbar-inverse .nav-collapse .navbar-form, + .navbar-inverse .nav-collapse .navbar-search { + border-top-color: #111111; + border-bottom-color: #111111; + } + .navbar .nav-collapse .nav.pull-right { + float: none; + margin-left: 0; + } + .nav-collapse, + .nav-collapse.collapse { + overflow: hidden; + height: 0; + } + .navbar .btn-navbar { + display: block; + } + .navbar-static .navbar-inner { + padding-left: 10px; + padding-right: 10px; + } +} +@media (min-width: 979px + 1) { + .nav-collapse.collapse { + height: auto !important; + overflow: visible !important; + } +} + diff --git a/openid-connect-server-webapp/src/main/webapp/resources/bootstrap2/css/bootstrap.css b/openid-connect-server-webapp/src/main/webapp/resources/bootstrap2/css/bootstrap.css new file mode 100644 index 0000000000..dd320d684b --- /dev/null +++ b/openid-connect-server-webapp/src/main/webapp/resources/bootstrap2/css/bootstrap.css @@ -0,0 +1,5236 @@ +/*! + * Bootstrap v2.3.2 + * + * Copyright 2013 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world by @mdo and @fat. + */ +.clearfix { + *zoom: 1; +} +.clearfix:before, +.clearfix:after { + display: table; + content: ""; + line-height: 0; +} +.clearfix:after { + clear: both; +} +.hide-text { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.input-block-level { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section { + display: block; +} +audio, +canvas, +video { + display: inline-block; + *display: inline; + *zoom: 1; +} +audio:not([controls]) { + display: none; +} +html { + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} +a:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +a:hover, +a:active { + outline: 0; +} +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + /* Responsive images (ensure images don't scale beyond their parents) */ + max-width: 100%; + /* Part 1: Set a maxium relative to the parent */ + width: auto\9; + /* IE7-8 need help adjusting responsive images */ + height: auto; + /* Part 2: Scale the height according to the width, otherwise you get stretching */ + vertical-align: middle; + border: 0; + -ms-interpolation-mode: bicubic; +} +#map_canvas img, +.google-maps img { + max-width: none; +} +button, +input, +select, +textarea { + margin: 0; + font-size: 100%; + vertical-align: middle; +} +button, +input { + *overflow: visible; + line-height: normal; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +label, +select, +button, +input[type="button"], +input[type="reset"], +input[type="submit"], +input[type="radio"], +input[type="checkbox"] { + cursor: pointer; +} +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; +} +input[type="search"]::-webkit-search-decoration, +input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none; +} +textarea { + overflow: auto; + vertical-align: top; +} +@media print { + * { + text-shadow: none !important; + color: #000 !important; + background: transparent !important; + box-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + .ir a:after, + a[href^="javascript:"]:after, + a[href^="#"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + @page { + margin: 0.5cm; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } +} +body { + margin: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 20px; + color: #333333; + background-color: #ffffff; +} +a { + color: #0088cc; + text-decoration: none; +} +a:hover, +a:focus { + color: #005580; + text-decoration: underline; +} +.img-rounded { + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} +.img-polaroid { + padding: 4px; + background-color: #fff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} +.img-circle { + -webkit-border-radius: 500px; + -moz-border-radius: 500px; + border-radius: 500px; +} +.row { + margin-left: -20px; + *zoom: 1; +} +.row:before, +.row:after { + display: table; + content: ""; + line-height: 0; +} +.row:after { + clear: both; +} +[class*="span"] { + float: left; + min-height: 1px; + margin-left: 20px; +} +.container, +.navbar-static-top .container, +.navbar-fixed-top .container, +.navbar-fixed-bottom .container { + width: 940px; +} +.span12 { + width: 940px; +} +.span11 { + width: 860px; +} +.span10 { + width: 780px; +} +.span9 { + width: 700px; +} +.span8 { + width: 620px; +} +.span7 { + width: 540px; +} +.span6 { + width: 460px; +} +.span5 { + width: 380px; +} +.span4 { + width: 300px; +} +.span3 { + width: 220px; +} +.span2 { + width: 140px; +} +.span1 { + width: 60px; +} +.offset12 { + margin-left: 980px; +} +.offset11 { + margin-left: 900px; +} +.offset10 { + margin-left: 820px; +} +.offset9 { + margin-left: 740px; +} +.offset8 { + margin-left: 660px; +} +.offset7 { + margin-left: 580px; +} +.offset6 { + margin-left: 500px; +} +.offset5 { + margin-left: 420px; +} +.offset4 { + margin-left: 340px; +} +.offset3 { + margin-left: 260px; +} +.offset2 { + margin-left: 180px; +} +.offset1 { + margin-left: 100px; +} +.row-fluid { + width: 100%; + *zoom: 1; +} +.row-fluid:before, +.row-fluid:after { + display: table; + content: ""; + line-height: 0; +} +.row-fluid:after { + clear: both; +} +.row-fluid [class*="span"] { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + float: left; + margin-left: 2.12765957%; + *margin-left: 2.07446809%; +} +.row-fluid [class*="span"]:first-child { + margin-left: 0; +} +.row-fluid .controls-row [class*="span"] + [class*="span"] { + margin-left: 2.12765957%; +} +.row-fluid .span12 { + width: 100%; + *width: 99.94680851%; +} +.row-fluid .span11 { + width: 91.4893617%; + *width: 91.43617021%; +} +.row-fluid .span10 { + width: 82.9787234%; + *width: 82.92553191%; +} +.row-fluid .span9 { + width: 74.46808511%; + *width: 74.41489362%; +} +.row-fluid .span8 { + width: 65.95744681%; + *width: 65.90425532%; +} +.row-fluid .span7 { + width: 57.44680851%; + *width: 57.39361702%; +} +.row-fluid .span6 { + width: 48.93617021%; + *width: 48.88297872%; +} +.row-fluid .span5 { + width: 40.42553191%; + *width: 40.37234043%; +} +.row-fluid .span4 { + width: 31.91489362%; + *width: 31.86170213%; +} +.row-fluid .span3 { + width: 23.40425532%; + *width: 23.35106383%; +} +.row-fluid .span2 { + width: 14.89361702%; + *width: 14.84042553%; +} +.row-fluid .span1 { + width: 6.38297872%; + *width: 6.32978723%; +} +.row-fluid .offset12 { + margin-left: 104.25531915%; + *margin-left: 104.14893617%; +} +.row-fluid .offset12:first-child { + margin-left: 102.12765957%; + *margin-left: 102.0212766%; +} +.row-fluid .offset11 { + margin-left: 95.74468085%; + *margin-left: 95.63829787%; +} +.row-fluid .offset11:first-child { + margin-left: 93.61702128%; + *margin-left: 93.5106383%; +} +.row-fluid .offset10 { + margin-left: 87.23404255%; + *margin-left: 87.12765957%; +} +.row-fluid .offset10:first-child { + margin-left: 85.10638298%; + *margin-left: 85%; +} +.row-fluid .offset9 { + margin-left: 78.72340426%; + *margin-left: 78.61702128%; +} +.row-fluid .offset9:first-child { + margin-left: 76.59574468%; + *margin-left: 76.4893617%; +} +.row-fluid .offset8 { + margin-left: 70.21276596%; + *margin-left: 70.10638298%; +} +.row-fluid .offset8:first-child { + margin-left: 68.08510638%; + *margin-left: 67.9787234%; +} +.row-fluid .offset7 { + margin-left: 61.70212766%; + *margin-left: 61.59574468%; +} +.row-fluid .offset7:first-child { + margin-left: 59.57446809%; + *margin-left: 59.46808511%; +} +.row-fluid .offset6 { + margin-left: 53.19148936%; + *margin-left: 53.08510638%; +} +.row-fluid .offset6:first-child { + margin-left: 51.06382979%; + *margin-left: 50.95744681%; +} +.row-fluid .offset5 { + margin-left: 44.68085106%; + *margin-left: 44.57446809%; +} +.row-fluid .offset5:first-child { + margin-left: 42.55319149%; + *margin-left: 42.44680851%; +} +.row-fluid .offset4 { + margin-left: 36.17021277%; + *margin-left: 36.06382979%; +} +.row-fluid .offset4:first-child { + margin-left: 34.04255319%; + *margin-left: 33.93617021%; +} +.row-fluid .offset3 { + margin-left: 27.65957447%; + *margin-left: 27.55319149%; +} +.row-fluid .offset3:first-child { + margin-left: 25.53191489%; + *margin-left: 25.42553191%; +} +.row-fluid .offset2 { + margin-left: 19.14893617%; + *margin-left: 19.04255319%; +} +.row-fluid .offset2:first-child { + margin-left: 17.0212766%; + *margin-left: 16.91489362%; +} +.row-fluid .offset1 { + margin-left: 10.63829787%; + *margin-left: 10.53191489%; +} +.row-fluid .offset1:first-child { + margin-left: 8.5106383%; + *margin-left: 8.40425532%; +} +[class*="span"].hide, +.row-fluid [class*="span"].hide { + display: none; +} +[class*="span"].pull-right, +.row-fluid [class*="span"].pull-right { + float: right; +} +.container { + margin-right: auto; + margin-left: auto; + *zoom: 1; +} +.container:before, +.container:after { + display: table; + content: ""; + line-height: 0; +} +.container:after { + clear: both; +} +.container-fluid { + padding-right: 20px; + padding-left: 20px; + *zoom: 1; +} +.container-fluid:before, +.container-fluid:after { + display: table; + content: ""; + line-height: 0; +} +.container-fluid:after { + clear: both; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 21px; + font-weight: 200; + line-height: 30px; +} +small { + font-size: 85%; +} +strong { + font-weight: bold; +} +em { + font-style: italic; +} +cite { + font-style: normal; +} +.muted { + color: #999999; +} +a.muted:hover, +a.muted:focus { + color: #808080; +} +.text-warning { + color: #c09853; +} +a.text-warning:hover, +a.text-warning:focus { + color: #a47e3c; +} +.text-error { + color: #b94a48; +} +a.text-error:hover, +a.text-error:focus { + color: #953b39; +} +.text-info { + color: #3a87ad; +} +a.text-info:hover, +a.text-info:focus { + color: #2d6987; +} +.text-success { + color: #468847; +} +a.text-success:hover, +a.text-success:focus { + color: #356635; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +h1, +h2, +h3, +h4, +h5, +h6 { + margin: 10px 0; + font-family: inherit; + font-weight: bold; + line-height: 20px; + color: inherit; + text-rendering: optimizelegibility; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small { + font-weight: normal; + line-height: 1; + color: #999999; +} +h1, +h2, +h3 { + line-height: 40px; +} +h1 { + font-size: 38.5px; +} +h2 { + font-size: 31.5px; +} +h3 { + font-size: 24.5px; +} +h4 { + font-size: 17.5px; +} +h5 { + font-size: 14px; +} +h6 { + font-size: 11.9px; +} +h1 small { + font-size: 24.5px; +} +h2 small { + font-size: 17.5px; +} +h3 small { + font-size: 14px; +} +h4 small { + font-size: 14px; +} +.page-header { + padding-bottom: 9px; + margin: 20px 0 30px; + border-bottom: 1px solid #eeeeee; +} +ul, +ol { + padding: 0; + margin: 0 0 10px 25px; +} +ul ul, +ul ol, +ol ol, +ol ul { + margin-bottom: 0; +} +li { + line-height: 20px; +} +ul.unstyled, +ol.unstyled { + margin-left: 0; + list-style: none; +} +ul.inline, +ol.inline { + margin-left: 0; + list-style: none; +} +ul.inline > li, +ol.inline > li { + display: inline-block; + *display: inline; + /* IE7 inline-block hack */ + *zoom: 1; + padding-left: 5px; + padding-right: 5px; +} +dl { + margin-bottom: 20px; +} +dt, +dd { + line-height: 20px; +} +dt { + font-weight: bold; +} +dd { + margin-left: 10px; +} +.dl-horizontal { + *zoom: 1; +} +.dl-horizontal:before, +.dl-horizontal:after { + display: table; + content: ""; + line-height: 0; +} +.dl-horizontal:after { + clear: both; +} +.dl-horizontal dt { + float: left; + width: 160px; + clear: left; + text-align: right; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.dl-horizontal dd { + margin-left: 180px; +} +hr { + margin: 20px 0; + border: 0; + border-top: 1px solid #eeeeee; + border-bottom: 1px solid #ffffff; +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #999999; +} +abbr.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 0 0 0 15px; + margin: 0 0 20px; + border-left: 5px solid #eeeeee; +} +blockquote p { + margin-bottom: 0; + font-size: 17.5px; + font-weight: 300; + line-height: 1.25; +} +blockquote small { + display: block; + line-height: 20px; + color: #999999; +} +blockquote small:before { + content: '\2014 \00A0'; +} +blockquote.pull-right { + float: right; + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eeeeee; + border-left: 0; +} +blockquote.pull-right p, +blockquote.pull-right small { + text-align: right; +} +blockquote.pull-right small:before { + content: ''; +} +blockquote.pull-right small:after { + content: '\00A0 \2014'; +} +q:before, +q:after, +blockquote:before, +blockquote:after { + content: ""; +} +address { + display: block; + margin-bottom: 20px; + font-style: normal; + line-height: 20px; +} +code, +pre { + padding: 0 3px 2px; + font-family: Monaco, Menlo, Consolas, "Courier New", monospace; + font-size: 12px; + color: #333333; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} +code { + padding: 2px 4px; + color: #d14; + background-color: #f7f7f9; + border: 1px solid #e1e1e8; + white-space: nowrap; +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 20px; + word-break: break-all; + word-wrap: break-word; + white-space: pre; + white-space: pre-wrap; + background-color: #f5f5f5; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.15); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +pre.prettyprint { + margin-bottom: 20px; +} +pre code { + padding: 0; + color: inherit; + white-space: pre; + white-space: pre-wrap; + background-color: transparent; + border: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +form { + margin: 0 0 20px; +} +fieldset { + padding: 0; + margin: 0; + border: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: 40px; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +legend small { + font-size: 15px; + color: #999999; +} +label, +input, +button, +select, +textarea { + font-size: 14px; + font-weight: normal; + line-height: 20px; +} +input, +button, +select, +textarea { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; +} +label { + display: block; + margin-bottom: 5px; +} +select, +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"], +.uneditable-input { + display: inline-block; + height: 20px; + padding: 4px 6px; + margin-bottom: 10px; + font-size: 14px; + line-height: 20px; + color: #555555; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + vertical-align: middle; +} +input, +textarea, +.uneditable-input { + width: 206px; +} +textarea { + height: auto; +} +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"], +.uneditable-input { + background-color: #ffffff; + border: 1px solid #cccccc; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border linear .2s, box-shadow linear .2s; + -moz-transition: border linear .2s, box-shadow linear .2s; + -o-transition: border linear .2s, box-shadow linear .2s; + transition: border linear .2s, box-shadow linear .2s; +} +textarea:focus, +input[type="text"]:focus, +input[type="password"]:focus, +input[type="datetime"]:focus, +input[type="datetime-local"]:focus, +input[type="date"]:focus, +input[type="month"]:focus, +input[type="time"]:focus, +input[type="week"]:focus, +input[type="number"]:focus, +input[type="email"]:focus, +input[type="url"]:focus, +input[type="search"]:focus, +input[type="tel"]:focus, +input[type="color"]:focus, +.uneditable-input:focus { + border-color: rgba(82, 168, 236, 0.8); + outline: 0; + outline: thin dotted \9; + /* IE6-9 */ + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6); + -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6); +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + *margin-top: 0; + /* IE7 */ + margin-top: 1px \9; + /* IE8-9 */ + line-height: normal; +} +input[type="file"], +input[type="image"], +input[type="submit"], +input[type="reset"], +input[type="button"], +input[type="radio"], +input[type="checkbox"] { + width: auto; +} +select, +input[type="file"] { + height: 30px; + /* In IE7, the height of the select element cannot be changed by height, only font-size */ + *margin-top: 4px; + /* For IE7, add top margin to align select with labels */ + line-height: 30px; +} +select { + width: 220px; + border: 1px solid #cccccc; + background-color: #ffffff; +} +select[multiple], +select[size] { + height: auto; +} +select:focus, +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.uneditable-input, +.uneditable-textarea { + color: #999999; + background-color: #fcfcfc; + border-color: #cccccc; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + cursor: not-allowed; +} +.uneditable-input { + overflow: hidden; + white-space: nowrap; +} +.uneditable-textarea { + width: auto; + height: auto; +} +input:-moz-placeholder, +textarea:-moz-placeholder { + color: #999999; +} +input:-ms-input-placeholder, +textarea:-ms-input-placeholder { + color: #999999; +} +input::-webkit-input-placeholder, +textarea::-webkit-input-placeholder { + color: #999999; +} +.radio, +.checkbox { + min-height: 20px; + padding-left: 20px; +} +.radio input[type="radio"], +.checkbox input[type="checkbox"] { + float: left; + margin-left: -20px; +} +.controls > .radio:first-child, +.controls > .checkbox:first-child { + padding-top: 5px; +} +.radio.inline, +.checkbox.inline { + display: inline-block; + padding-top: 5px; + margin-bottom: 0; + vertical-align: middle; +} +.radio.inline + .radio.inline, +.checkbox.inline + .checkbox.inline { + margin-left: 10px; +} +.input-mini { + width: 60px; +} +.input-small { + width: 90px; +} +.input-medium { + width: 150px; +} +.input-large { + width: 210px; +} +.input-xlarge { + width: 270px; +} +.input-xxlarge { + width: 530px; +} +input[class*="span"], +select[class*="span"], +textarea[class*="span"], +.uneditable-input[class*="span"], +.row-fluid input[class*="span"], +.row-fluid select[class*="span"], +.row-fluid textarea[class*="span"], +.row-fluid .uneditable-input[class*="span"] { + float: none; + margin-left: 0; +} +.input-append input[class*="span"], +.input-append .uneditable-input[class*="span"], +.input-prepend input[class*="span"], +.input-prepend .uneditable-input[class*="span"], +.row-fluid input[class*="span"], +.row-fluid select[class*="span"], +.row-fluid textarea[class*="span"], +.row-fluid .uneditable-input[class*="span"], +.row-fluid .input-prepend [class*="span"], +.row-fluid .input-append [class*="span"] { + display: inline-block; +} +input, +textarea, +.uneditable-input { + margin-left: 0; +} +.controls-row [class*="span"] + [class*="span"] { + margin-left: 20px; +} +input.span12, +textarea.span12, +.uneditable-input.span12 { + width: 926px; +} +input.span11, +textarea.span11, +.uneditable-input.span11 { + width: 846px; +} +input.span10, +textarea.span10, +.uneditable-input.span10 { + width: 766px; +} +input.span9, +textarea.span9, +.uneditable-input.span9 { + width: 686px; +} +input.span8, +textarea.span8, +.uneditable-input.span8 { + width: 606px; +} +input.span7, +textarea.span7, +.uneditable-input.span7 { + width: 526px; +} +input.span6, +textarea.span6, +.uneditable-input.span6 { + width: 446px; +} +input.span5, +textarea.span5, +.uneditable-input.span5 { + width: 366px; +} +input.span4, +textarea.span4, +.uneditable-input.span4 { + width: 286px; +} +input.span3, +textarea.span3, +.uneditable-input.span3 { + width: 206px; +} +input.span2, +textarea.span2, +.uneditable-input.span2 { + width: 126px; +} +input.span1, +textarea.span1, +.uneditable-input.span1 { + width: 46px; +} +.controls-row { + *zoom: 1; +} +.controls-row:before, +.controls-row:after { + display: table; + content: ""; + line-height: 0; +} +.controls-row:after { + clear: both; +} +.controls-row [class*="span"], +.row-fluid .controls-row [class*="span"] { + float: left; +} +.controls-row .checkbox[class*="span"], +.controls-row .radio[class*="span"] { + padding-top: 5px; +} +input[disabled], +select[disabled], +textarea[disabled], +input[readonly], +select[readonly], +textarea[readonly] { + cursor: not-allowed; + background-color: #eeeeee; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"][readonly], +input[type="checkbox"][readonly] { + background-color: transparent; +} +.control-group.warning .control-label, +.control-group.warning .help-block, +.control-group.warning .help-inline { + color: #c09853; +} +.control-group.warning .checkbox, +.control-group.warning .radio, +.control-group.warning input, +.control-group.warning select, +.control-group.warning textarea { + color: #c09853; +} +.control-group.warning input, +.control-group.warning select, +.control-group.warning textarea { + border-color: #c09853; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.control-group.warning input:focus, +.control-group.warning select:focus, +.control-group.warning textarea:focus { + border-color: #a47e3c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; +} +.control-group.warning .input-prepend .add-on, +.control-group.warning .input-append .add-on { + color: #c09853; + background-color: #fcf8e3; + border-color: #c09853; +} +.control-group.error .control-label, +.control-group.error .help-block, +.control-group.error .help-inline { + color: #b94a48; +} +.control-group.error .checkbox, +.control-group.error .radio, +.control-group.error input, +.control-group.error select, +.control-group.error textarea { + color: #b94a48; +} +.control-group.error input, +.control-group.error select, +.control-group.error textarea { + border-color: #b94a48; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.control-group.error input:focus, +.control-group.error select:focus, +.control-group.error textarea:focus { + border-color: #953b39; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; +} +.control-group.error .input-prepend .add-on, +.control-group.error .input-append .add-on { + color: #b94a48; + background-color: #f2dede; + border-color: #b94a48; +} +.control-group.success .control-label, +.control-group.success .help-block, +.control-group.success .help-inline { + color: #468847; +} +.control-group.success .checkbox, +.control-group.success .radio, +.control-group.success input, +.control-group.success select, +.control-group.success textarea { + color: #468847; +} +.control-group.success input, +.control-group.success select, +.control-group.success textarea { + border-color: #468847; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.control-group.success input:focus, +.control-group.success select:focus, +.control-group.success textarea:focus { + border-color: #356635; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; +} +.control-group.success .input-prepend .add-on, +.control-group.success .input-append .add-on { + color: #468847; + background-color: #dff0d8; + border-color: #468847; +} +.control-group.info .control-label, +.control-group.info .help-block, +.control-group.info .help-inline { + color: #3a87ad; +} +.control-group.info .checkbox, +.control-group.info .radio, +.control-group.info input, +.control-group.info select, +.control-group.info textarea { + color: #3a87ad; +} +.control-group.info input, +.control-group.info select, +.control-group.info textarea { + border-color: #3a87ad; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.control-group.info input:focus, +.control-group.info select:focus, +.control-group.info textarea:focus { + border-color: #2d6987; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; +} +.control-group.info .input-prepend .add-on, +.control-group.info .input-append .add-on { + color: #3a87ad; + background-color: #d9edf7; + border-color: #3a87ad; +} +input:focus:invalid, +textarea:focus:invalid, +select:focus:invalid { + color: #b94a48; + border-color: #ee5f5b; +} +input:focus:invalid:focus, +textarea:focus:invalid:focus, +select:focus:invalid:focus { + border-color: #e9322d; + -webkit-box-shadow: 0 0 6px #f8b9b7; + -moz-box-shadow: 0 0 6px #f8b9b7; + box-shadow: 0 0 6px #f8b9b7; +} +.form-actions { + padding: 19px 20px 20px; + margin-top: 20px; + margin-bottom: 20px; + background-color: #f5f5f5; + border-top: 1px solid #e5e5e5; + *zoom: 1; +} +.form-actions:before, +.form-actions:after { + display: table; + content: ""; + line-height: 0; +} +.form-actions:after { + clear: both; +} +.help-block, +.help-inline { + color: #595959; +} +.help-block { + display: block; + margin-bottom: 10px; +} +.help-inline { + display: inline-block; + *display: inline; + /* IE7 inline-block hack */ + *zoom: 1; + vertical-align: middle; + padding-left: 5px; +} +.input-append, +.input-prepend { + display: inline-block; + margin-bottom: 10px; + vertical-align: middle; + font-size: 0; + white-space: nowrap; +} +.input-append input, +.input-prepend input, +.input-append select, +.input-prepend select, +.input-append .uneditable-input, +.input-prepend .uneditable-input, +.input-append .dropdown-menu, +.input-prepend .dropdown-menu, +.input-append .popover, +.input-prepend .popover { + font-size: 14px; +} +.input-append input, +.input-prepend input, +.input-append select, +.input-prepend select, +.input-append .uneditable-input, +.input-prepend .uneditable-input { + position: relative; + margin-bottom: 0; + *margin-left: 0; + vertical-align: top; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} +.input-append input:focus, +.input-prepend input:focus, +.input-append select:focus, +.input-prepend select:focus, +.input-append .uneditable-input:focus, +.input-prepend .uneditable-input:focus { + z-index: 2; +} +.input-append .add-on, +.input-prepend .add-on { + display: inline-block; + width: auto; + height: 20px; + min-width: 16px; + padding: 4px 5px; + font-size: 14px; + font-weight: normal; + line-height: 20px; + text-align: center; + text-shadow: 0 1px 0 #ffffff; + background-color: #eeeeee; + border: 1px solid #ccc; +} +.input-append .add-on, +.input-prepend .add-on, +.input-append .btn, +.input-prepend .btn, +.input-append .btn-group > .dropdown-toggle, +.input-prepend .btn-group > .dropdown-toggle { + vertical-align: top; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.input-append .active, +.input-prepend .active { + background-color: #a9dba9; + border-color: #46a546; +} +.input-prepend .add-on, +.input-prepend .btn { + margin-right: -1px; +} +.input-prepend .add-on:first-child, +.input-prepend .btn:first-child { + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} +.input-append input, +.input-append select, +.input-append .uneditable-input { + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} +.input-append input + .btn-group .btn:last-child, +.input-append select + .btn-group .btn:last-child, +.input-append .uneditable-input + .btn-group .btn:last-child { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} +.input-append .add-on, +.input-append .btn, +.input-append .btn-group { + margin-left: -1px; +} +.input-append .add-on:last-child, +.input-append .btn:last-child, +.input-append .btn-group:last-child > .dropdown-toggle { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} +.input-prepend.input-append input, +.input-prepend.input-append select, +.input-prepend.input-append .uneditable-input { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.input-prepend.input-append input + .btn-group .btn, +.input-prepend.input-append select + .btn-group .btn, +.input-prepend.input-append .uneditable-input + .btn-group .btn { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} +.input-prepend.input-append .add-on:first-child, +.input-prepend.input-append .btn:first-child { + margin-right: -1px; + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} +.input-prepend.input-append .add-on:last-child, +.input-prepend.input-append .btn:last-child { + margin-left: -1px; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} +.input-prepend.input-append .btn-group:first-child { + margin-left: 0; +} +input.search-query { + padding-right: 14px; + padding-right: 4px \9; + padding-left: 14px; + padding-left: 4px \9; + /* IE7-8 doesn't have border-radius, so don't indent the padding */ + margin-bottom: 0; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} +/* Allow for input prepend/append in search forms */ +.form-search .input-append .search-query, +.form-search .input-prepend .search-query { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.form-search .input-append .search-query { + -webkit-border-radius: 14px 0 0 14px; + -moz-border-radius: 14px 0 0 14px; + border-radius: 14px 0 0 14px; +} +.form-search .input-append .btn { + -webkit-border-radius: 0 14px 14px 0; + -moz-border-radius: 0 14px 14px 0; + border-radius: 0 14px 14px 0; +} +.form-search .input-prepend .search-query { + -webkit-border-radius: 0 14px 14px 0; + -moz-border-radius: 0 14px 14px 0; + border-radius: 0 14px 14px 0; +} +.form-search .input-prepend .btn { + -webkit-border-radius: 14px 0 0 14px; + -moz-border-radius: 14px 0 0 14px; + border-radius: 14px 0 0 14px; +} +.form-search input, +.form-inline input, +.form-horizontal input, +.form-search textarea, +.form-inline textarea, +.form-horizontal textarea, +.form-search select, +.form-inline select, +.form-horizontal select, +.form-search .help-inline, +.form-inline .help-inline, +.form-horizontal .help-inline, +.form-search .uneditable-input, +.form-inline .uneditable-input, +.form-horizontal .uneditable-input, +.form-search .input-prepend, +.form-inline .input-prepend, +.form-horizontal .input-prepend, +.form-search .input-append, +.form-inline .input-append, +.form-horizontal .input-append { + display: inline-block; + *display: inline; + /* IE7 inline-block hack */ + *zoom: 1; + margin-bottom: 0; + vertical-align: middle; +} +.form-search .hide, +.form-inline .hide, +.form-horizontal .hide { + display: none; +} +.form-search label, +.form-inline label, +.form-search .btn-group, +.form-inline .btn-group { + display: inline-block; +} +.form-search .input-append, +.form-inline .input-append, +.form-search .input-prepend, +.form-inline .input-prepend { + margin-bottom: 0; +} +.form-search .radio, +.form-search .checkbox, +.form-inline .radio, +.form-inline .checkbox { + padding-left: 0; + margin-bottom: 0; + vertical-align: middle; +} +.form-search .radio input[type="radio"], +.form-search .checkbox input[type="checkbox"], +.form-inline .radio input[type="radio"], +.form-inline .checkbox input[type="checkbox"] { + float: left; + margin-right: 3px; + margin-left: 0; +} +.control-group { + margin-bottom: 10px; +} +legend + .control-group { + margin-top: 20px; + -webkit-margin-top-collapse: separate; +} +.form-horizontal .control-group { + margin-bottom: 20px; + *zoom: 1; +} +.form-horizontal .control-group:before, +.form-horizontal .control-group:after { + display: table; + content: ""; + line-height: 0; +} +.form-horizontal .control-group:after { + clear: both; +} +.form-horizontal .control-label { + float: left; + width: 160px; + padding-top: 5px; + text-align: right; +} +.form-horizontal .controls { + *display: inline-block; + *padding-left: 20px; + margin-left: 180px; + *margin-left: 0; +} +.form-horizontal .controls:first-child { + *padding-left: 180px; +} +.form-horizontal .help-block { + margin-bottom: 0; +} +.form-horizontal input + .help-block, +.form-horizontal select + .help-block, +.form-horizontal textarea + .help-block, +.form-horizontal .uneditable-input + .help-block, +.form-horizontal .input-prepend + .help-block, +.form-horizontal .input-append + .help-block { + margin-top: 10px; +} +.form-horizontal .form-actions { + padding-left: 180px; +} +table { + max-width: 100%; + background-color: transparent; + border-collapse: collapse; + border-spacing: 0; +} +.table { + width: 100%; + margin-bottom: 20px; +} +.table th, +.table td { + padding: 8px; + line-height: 20px; + text-align: left; + vertical-align: top; + border-top: 1px solid #dddddd; +} +.table th { + font-weight: bold; +} +.table thead th { + vertical-align: bottom; +} +.table caption + thead tr:first-child th, +.table caption + thead tr:first-child td, +.table colgroup + thead tr:first-child th, +.table colgroup + thead tr:first-child td, +.table thead:first-child tr:first-child th, +.table thead:first-child tr:first-child td { + border-top: 0; +} +.table tbody + tbody { + border-top: 2px solid #dddddd; +} +.table .table { + background-color: #ffffff; +} +.table-condensed th, +.table-condensed td { + padding: 4px 5px; +} +.table-bordered { + border: 1px solid #dddddd; + border-collapse: separate; + *border-collapse: collapse; + border-left: 0; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.table-bordered th, +.table-bordered td { + border-left: 1px solid #dddddd; +} +.table-bordered caption + thead tr:first-child th, +.table-bordered caption + tbody tr:first-child th, +.table-bordered caption + tbody tr:first-child td, +.table-bordered colgroup + thead tr:first-child th, +.table-bordered colgroup + tbody tr:first-child th, +.table-bordered colgroup + tbody tr:first-child td, +.table-bordered thead:first-child tr:first-child th, +.table-bordered tbody:first-child tr:first-child th, +.table-bordered tbody:first-child tr:first-child td { + border-top: 0; +} +.table-bordered thead:first-child tr:first-child > th:first-child, +.table-bordered tbody:first-child tr:first-child > td:first-child, +.table-bordered tbody:first-child tr:first-child > th:first-child { + -webkit-border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; + border-top-left-radius: 4px; +} +.table-bordered thead:first-child tr:first-child > th:last-child, +.table-bordered tbody:first-child tr:first-child > td:last-child, +.table-bordered tbody:first-child tr:first-child > th:last-child { + -webkit-border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; + border-top-right-radius: 4px; +} +.table-bordered thead:last-child tr:last-child > th:first-child, +.table-bordered tbody:last-child tr:last-child > td:first-child, +.table-bordered tbody:last-child tr:last-child > th:first-child, +.table-bordered tfoot:last-child tr:last-child > td:first-child, +.table-bordered tfoot:last-child tr:last-child > th:first-child { + -webkit-border-bottom-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + border-bottom-left-radius: 4px; +} +.table-bordered thead:last-child tr:last-child > th:last-child, +.table-bordered tbody:last-child tr:last-child > td:last-child, +.table-bordered tbody:last-child tr:last-child > th:last-child, +.table-bordered tfoot:last-child tr:last-child > td:last-child, +.table-bordered tfoot:last-child tr:last-child > th:last-child { + -webkit-border-bottom-right-radius: 4px; + -moz-border-radius-bottomright: 4px; + border-bottom-right-radius: 4px; +} +.table-bordered tfoot + tbody:last-child tr:last-child td:first-child { + -webkit-border-bottom-left-radius: 0; + -moz-border-radius-bottomleft: 0; + border-bottom-left-radius: 0; +} +.table-bordered tfoot + tbody:last-child tr:last-child td:last-child { + -webkit-border-bottom-right-radius: 0; + -moz-border-radius-bottomright: 0; + border-bottom-right-radius: 0; +} +.table-bordered caption + thead tr:first-child th:first-child, +.table-bordered caption + tbody tr:first-child td:first-child, +.table-bordered colgroup + thead tr:first-child th:first-child, +.table-bordered colgroup + tbody tr:first-child td:first-child { + -webkit-border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; + border-top-left-radius: 4px; +} +.table-bordered caption + thead tr:first-child th:last-child, +.table-bordered caption + tbody tr:first-child td:last-child, +.table-bordered colgroup + thead tr:first-child th:last-child, +.table-bordered colgroup + tbody tr:first-child td:last-child { + -webkit-border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; + border-top-right-radius: 4px; +} +.table-striped tbody > tr:nth-child(odd) > td, +.table-striped tbody > tr:nth-child(odd) > th { + background-color: #f9f9f9; +} +.table-hover tbody tr:hover > td, +.table-hover tbody tr:hover > th { + background-color: #f5f5f5; +} +table td[class*="span"], +table th[class*="span"], +.row-fluid table td[class*="span"], +.row-fluid table th[class*="span"] { + display: table-cell; + float: none; + margin-left: 0; +} +.table td.span1, +.table th.span1 { + float: none; + width: 44px; + margin-left: 0; +} +.table td.span2, +.table th.span2 { + float: none; + width: 124px; + margin-left: 0; +} +.table td.span3, +.table th.span3 { + float: none; + width: 204px; + margin-left: 0; +} +.table td.span4, +.table th.span4 { + float: none; + width: 284px; + margin-left: 0; +} +.table td.span5, +.table th.span5 { + float: none; + width: 364px; + margin-left: 0; +} +.table td.span6, +.table th.span6 { + float: none; + width: 444px; + margin-left: 0; +} +.table td.span7, +.table th.span7 { + float: none; + width: 524px; + margin-left: 0; +} +.table td.span8, +.table th.span8 { + float: none; + width: 604px; + margin-left: 0; +} +.table td.span9, +.table th.span9 { + float: none; + width: 684px; + margin-left: 0; +} +.table td.span10, +.table th.span10 { + float: none; + width: 764px; + margin-left: 0; +} +.table td.span11, +.table th.span11 { + float: none; + width: 844px; + margin-left: 0; +} +.table td.span12, +.table th.span12 { + float: none; + width: 924px; + margin-left: 0; +} +.table tbody tr.success > td { + background-color: #dff0d8; +} +.table tbody tr.error > td { + background-color: #f2dede; +} +.table tbody tr.warning > td { + background-color: #fcf8e3; +} +.table tbody tr.info > td { + background-color: #d9edf7; +} +.table-hover tbody tr.success:hover > td { + background-color: #d0e9c6; +} +.table-hover tbody tr.error:hover > td { + background-color: #ebcccc; +} +.table-hover tbody tr.warning:hover > td { + background-color: #faf2cc; +} +.table-hover tbody tr.info:hover > td { + background-color: #c4e3f3; +} +[class^="icon-"], +[class*=" icon-"] { + display: inline-block; + width: 14px; + height: 14px; + *margin-right: .3em; + line-height: 14px; + vertical-align: text-top; + background-image: url("../img/glyphicons-halflings.png"); + background-position: 14px 14px; + background-repeat: no-repeat; + margin-top: 1px; +} +/* White icons with optional class, or on hover/focus/active states of certain elements */ +.icon-white, +.nav-pills > .active > a > [class^="icon-"], +.nav-pills > .active > a > [class*=" icon-"], +.nav-list > .active > a > [class^="icon-"], +.nav-list > .active > a > [class*=" icon-"], +.navbar-inverse .nav > .active > a > [class^="icon-"], +.navbar-inverse .nav > .active > a > [class*=" icon-"], +.dropdown-menu > li > a:hover > [class^="icon-"], +.dropdown-menu > li > a:focus > [class^="icon-"], +.dropdown-menu > li > a:hover > [class*=" icon-"], +.dropdown-menu > li > a:focus > [class*=" icon-"], +.dropdown-menu > .active > a > [class^="icon-"], +.dropdown-menu > .active > a > [class*=" icon-"], +.dropdown-submenu:hover > a > [class^="icon-"], +.dropdown-submenu:focus > a > [class^="icon-"], +.dropdown-submenu:hover > a > [class*=" icon-"], +.dropdown-submenu:focus > a > [class*=" icon-"] { + background-image: url("../img/glyphicons-halflings-white.png"); +} +.icon-glass { + background-position: 0 0; +} +.icon-music { + background-position: -24px 0; +} +.icon-search { + background-position: -48px 0; +} +.icon-envelope { + background-position: -72px 0; +} +.icon-heart { + background-position: -96px 0; +} +.icon-star { + background-position: -120px 0; +} +.icon-star-empty { + background-position: -144px 0; +} +.icon-user { + background-position: -168px 0; +} +.icon-film { + background-position: -192px 0; +} +.icon-th-large { + background-position: -216px 0; +} +.icon-th { + background-position: -240px 0; +} +.icon-th-list { + background-position: -264px 0; +} +.icon-ok { + background-position: -288px 0; +} +.icon-remove { + background-position: -312px 0; +} +.icon-zoom-in { + background-position: -336px 0; +} +.icon-zoom-out { + background-position: -360px 0; +} +.icon-off { + background-position: -384px 0; +} +.icon-signal { + background-position: -408px 0; +} +.icon-cog { + background-position: -432px 0; +} +.icon-trash { + background-position: -456px 0; +} +.icon-home { + background-position: 0 -24px; +} +.icon-file { + background-position: -24px -24px; +} +.icon-time { + background-position: -48px -24px; +} +.icon-road { + background-position: -72px -24px; +} +.icon-download-alt { + background-position: -96px -24px; +} +.icon-download { + background-position: -120px -24px; +} +.icon-upload { + background-position: -144px -24px; +} +.icon-inbox { + background-position: -168px -24px; +} +.icon-play-circle { + background-position: -192px -24px; +} +.icon-repeat { + background-position: -216px -24px; +} +.icon-refresh { + background-position: -240px -24px; +} +.icon-list-alt { + background-position: -264px -24px; +} +.icon-lock { + background-position: -287px -24px; +} +.icon-flag { + background-position: -312px -24px; +} +.icon-headphones { + background-position: -336px -24px; +} +.icon-volume-off { + background-position: -360px -24px; +} +.icon-volume-down { + background-position: -384px -24px; +} +.icon-volume-up { + background-position: -408px -24px; +} +.icon-qrcode { + background-position: -432px -24px; +} +.icon-barcode { + background-position: -456px -24px; +} +.icon-tag { + background-position: 0 -48px; +} +.icon-tags { + background-position: -25px -48px; +} +.icon-book { + background-position: -48px -48px; +} +.icon-bookmark { + background-position: -72px -48px; +} +.icon-print { + background-position: -96px -48px; +} +.icon-camera { + background-position: -120px -48px; +} +.icon-font { + background-position: -144px -48px; +} +.icon-bold { + background-position: -167px -48px; +} +.icon-italic { + background-position: -192px -48px; +} +.icon-text-height { + background-position: -216px -48px; +} +.icon-text-width { + background-position: -240px -48px; +} +.icon-align-left { + background-position: -264px -48px; +} +.icon-align-center { + background-position: -288px -48px; +} +.icon-align-right { + background-position: -312px -48px; +} +.icon-align-justify { + background-position: -336px -48px; +} +.icon-list { + background-position: -360px -48px; +} +.icon-indent-left { + background-position: -384px -48px; +} +.icon-indent-right { + background-position: -408px -48px; +} +.icon-facetime-video { + background-position: -432px -48px; +} +.icon-picture { + background-position: -456px -48px; +} +.icon-pencil { + background-position: 0 -72px; +} +.icon-map-marker { + background-position: -24px -72px; +} +.icon-adjust { + background-position: -48px -72px; +} +.icon-tint { + background-position: -72px -72px; +} +.icon-edit { + background-position: -96px -72px; +} +.icon-share { + background-position: -120px -72px; +} +.icon-check { + background-position: -144px -72px; +} +.icon-move { + background-position: -168px -72px; +} +.icon-step-backward { + background-position: -192px -72px; +} +.icon-fast-backward { + background-position: -216px -72px; +} +.icon-backward { + background-position: -240px -72px; +} +.icon-play { + background-position: -264px -72px; +} +.icon-pause { + background-position: -288px -72px; +} +.icon-stop { + background-position: -312px -72px; +} +.icon-forward { + background-position: -336px -72px; +} +.icon-fast-forward { + background-position: -360px -72px; +} +.icon-step-forward { + background-position: -384px -72px; +} +.icon-eject { + background-position: -408px -72px; +} +.icon-chevron-left { + background-position: -432px -72px; +} +.icon-chevron-right { + background-position: -456px -72px; +} +.icon-plus-sign { + background-position: 0 -96px; +} +.icon-minus-sign { + background-position: -24px -96px; +} +.icon-remove-sign { + background-position: -48px -96px; +} +.icon-ok-sign { + background-position: -72px -96px; +} +.icon-question-sign { + background-position: -96px -96px; +} +.icon-info-sign { + background-position: -120px -96px; +} +.icon-screenshot { + background-position: -144px -96px; +} +.icon-remove-circle { + background-position: -168px -96px; +} +.icon-ok-circle { + background-position: -192px -96px; +} +.icon-ban-circle { + background-position: -216px -96px; +} +.icon-arrow-left { + background-position: -240px -96px; +} +.icon-arrow-right { + background-position: -264px -96px; +} +.icon-arrow-up { + background-position: -289px -96px; +} +.icon-arrow-down { + background-position: -312px -96px; +} +.icon-share-alt { + background-position: -336px -96px; +} +.icon-resize-full { + background-position: -360px -96px; +} +.icon-resize-small { + background-position: -384px -96px; +} +.icon-plus { + background-position: -408px -96px; +} +.icon-minus { + background-position: -433px -96px; +} +.icon-asterisk { + background-position: -456px -96px; +} +.icon-exclamation-sign { + background-position: 0 -120px; +} +.icon-gift { + background-position: -24px -120px; +} +.icon-leaf { + background-position: -48px -120px; +} +.icon-fire { + background-position: -72px -120px; +} +.icon-eye-open { + background-position: -96px -120px; +} +.icon-eye-close { + background-position: -120px -120px; +} +.icon-warning-sign { + background-position: -144px -120px; +} +.icon-plane { + background-position: -168px -120px; +} +.icon-calendar { + background-position: -192px -120px; +} +.icon-random { + background-position: -216px -120px; + width: 16px; +} +.icon-comment { + background-position: -240px -120px; +} +.icon-magnet { + background-position: -264px -120px; +} +.icon-chevron-up { + background-position: -288px -120px; +} +.icon-chevron-down { + background-position: -313px -119px; +} +.icon-retweet { + background-position: -336px -120px; +} +.icon-shopping-cart { + background-position: -360px -120px; +} +.icon-folder-close { + background-position: -384px -120px; + width: 16px; +} +.icon-folder-open { + background-position: -408px -120px; + width: 16px; +} +.icon-resize-vertical { + background-position: -432px -119px; +} +.icon-resize-horizontal { + background-position: -456px -118px; +} +.icon-hdd { + background-position: 0 -144px; +} +.icon-bullhorn { + background-position: -24px -144px; +} +.icon-bell { + background-position: -48px -144px; +} +.icon-certificate { + background-position: -72px -144px; +} +.icon-thumbs-up { + background-position: -96px -144px; +} +.icon-thumbs-down { + background-position: -120px -144px; +} +.icon-hand-right { + background-position: -144px -144px; +} +.icon-hand-left { + background-position: -168px -144px; +} +.icon-hand-up { + background-position: -192px -144px; +} +.icon-hand-down { + background-position: -216px -144px; +} +.icon-circle-arrow-right { + background-position: -240px -144px; +} +.icon-circle-arrow-left { + background-position: -264px -144px; +} +.icon-circle-arrow-up { + background-position: -288px -144px; +} +.icon-circle-arrow-down { + background-position: -312px -144px; +} +.icon-globe { + background-position: -336px -144px; +} +.icon-wrench { + background-position: -360px -144px; +} +.icon-tasks { + background-position: -384px -144px; +} +.icon-filter { + background-position: -408px -144px; +} +.icon-briefcase { + background-position: -432px -144px; +} +.icon-fullscreen { + background-position: -456px -144px; +} +.dropup, +.dropdown { + position: relative; +} +.dropdown-toggle { + *margin-bottom: -3px; +} +.dropdown-toggle:active, +.open .dropdown-toggle { + outline: 0; +} +.caret { + display: inline-block; + width: 0; + height: 0; + vertical-align: top; + border-top: 4px solid #000000; + border-right: 4px solid transparent; + border-left: 4px solid transparent; + content: ""; +} +.dropdown .caret { + margin-top: 8px; + margin-left: 2px; +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + background-color: #ffffff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + *border-right-width: 2px; + *border-bottom-width: 2px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + *width: 100%; + height: 1px; + margin: 9px 1px; + *margin: -5px 0 5px; + overflow: hidden; + background-color: #e5e5e5; + border-bottom: 1px solid #ffffff; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 20px; + color: #333333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus, +.dropdown-submenu:hover > a, +.dropdown-submenu:focus > a { + text-decoration: none; + color: #ffffff; + background-color: #0081c2; + background-image: -moz-linear-gradient(top, #0088cc, #0077b3); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); + background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); + background-image: -o-linear-gradient(top, #0088cc, #0077b3); + background-image: linear-gradient(to bottom, #0088cc, #0077b3); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + outline: 0; + background-color: #0081c2; + background-image: -moz-linear-gradient(top, #0088cc, #0077b3); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); + background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); + background-image: -o-linear-gradient(top, #0088cc, #0077b3); + background-image: linear-gradient(to bottom, #0088cc, #0077b3); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #999999; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + cursor: default; +} +.open { + *z-index: 1000; +} +.open > .dropdown-menu { + display: block; +} +.dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px solid #000000; + content: ""; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; +} +.dropdown-submenu { + position: relative; +} +.dropdown-submenu > .dropdown-menu { + top: 0; + left: 100%; + margin-top: -6px; + margin-left: -1px; + -webkit-border-radius: 0 6px 6px 6px; + -moz-border-radius: 0 6px 6px 6px; + border-radius: 0 6px 6px 6px; +} +.dropdown-submenu:hover > .dropdown-menu { + display: block; +} +.dropup .dropdown-submenu > .dropdown-menu { + top: auto; + bottom: 0; + margin-top: 0; + margin-bottom: -2px; + -webkit-border-radius: 5px 5px 5px 0; + -moz-border-radius: 5px 5px 5px 0; + border-radius: 5px 5px 5px 0; +} +.dropdown-submenu > a:after { + display: block; + content: " "; + float: right; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + border-width: 5px 0 5px 5px; + border-left-color: #cccccc; + margin-top: 5px; + margin-right: -10px; +} +.dropdown-submenu:hover > a:after { + border-left-color: #ffffff; +} +.dropdown-submenu.pull-left { + float: none; +} +.dropdown-submenu.pull-left > .dropdown-menu { + left: -100%; + margin-left: 10px; + -webkit-border-radius: 6px 0 6px 6px; + -moz-border-radius: 6px 0 6px 6px; + border-radius: 6px 0 6px 6px; +} +.dropdown .dropdown-menu .nav-header { + padding-left: 20px; + padding-right: 20px; +} +.typeahead { + z-index: 1051; + margin-top: 2px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} +.well-large { + padding: 24px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} +.well-small { + padding: 9px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -moz-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height 0.35s ease; + -moz-transition: height 0.35s ease; + -o-transition: height 0.35s ease; + transition: height 0.35s ease; +} +.collapse.in { + height: auto; +} +.close { + float: right; + font-size: 20px; + font-weight: bold; + line-height: 20px; + color: #000000; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.2; + filter: alpha(opacity=20); +} +.close:hover, +.close:focus { + color: #000000; + text-decoration: none; + cursor: pointer; + opacity: 0.4; + filter: alpha(opacity=40); +} +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} +.btn { + display: inline-block; + *display: inline; + /* IE7 inline-block hack */ + *zoom: 1; + padding: 4px 12px; + margin-bottom: 0; + font-size: 14px; + line-height: 20px; + text-align: center; + vertical-align: middle; + cursor: pointer; + color: #333333; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + background-color: #f5f5f5; + background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); + background-image: linear-gradient(to bottom, #ffffff, #e6e6e6); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); + border-color: #e6e6e6 #e6e6e6 #bfbfbf; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #e6e6e6; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + border: 1px solid #cccccc; + *border: 0; + border-bottom-color: #b3b3b3; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + *margin-left: .3em; + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); + -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); + box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); +} +.btn:hover, +.btn:focus, +.btn:active, +.btn.active, +.btn.disabled, +.btn[disabled] { + color: #333333; + background-color: #e6e6e6; + *background-color: #d9d9d9; +} +.btn:active, +.btn.active { + background-color: #cccccc \9; +} +.btn:first-child { + *margin-left: 0; +} +.btn:hover, +.btn:focus { + color: #333333; + text-decoration: none; + background-position: 0 -15px; + -webkit-transition: background-position 0.1s linear; + -moz-transition: background-position 0.1s linear; + -o-transition: background-position 0.1s linear; + transition: background-position 0.1s linear; +} +.btn:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn.active, +.btn:active { + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); + -moz-box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); + box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); +} +.btn.disabled, +.btn[disabled] { + cursor: default; + background-image: none; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +.btn-large { + padding: 11px 19px; + font-size: 17.5px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} +.btn-large [class^="icon-"], +.btn-large [class*=" icon-"] { + margin-top: 4px; +} +.btn-small { + padding: 2px 10px; + font-size: 11.9px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} +.btn-small [class^="icon-"], +.btn-small [class*=" icon-"] { + margin-top: 0; +} +.btn-mini [class^="icon-"], +.btn-mini [class*=" icon-"] { + margin-top: -1px; +} +.btn-mini { + padding: 0 6px; + font-size: 10.5px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; + padding-left: 0; + padding-right: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.btn-primary.active, +.btn-warning.active, +.btn-danger.active, +.btn-success.active, +.btn-info.active, +.btn-inverse.active { + color: rgba(255, 255, 255, 0.75); +} +.btn-primary { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #006dcc; + background-image: -moz-linear-gradient(top, #0088cc, #0044cc); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); + background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); + background-image: -o-linear-gradient(top, #0088cc, #0044cc); + background-image: linear-gradient(to bottom, #0088cc, #0044cc); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0); + border-color: #0044cc #0044cc #002a80; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #0044cc; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.btn-primary:hover, +.btn-primary:focus, +.btn-primary:active, +.btn-primary.active, +.btn-primary.disabled, +.btn-primary[disabled] { + color: #ffffff; + background-color: #0044cc; + *background-color: #003bb3; +} +.btn-primary:active, +.btn-primary.active { + background-color: #003399 \9; +} +.btn-warning { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #faa732; + background-image: -moz-linear-gradient(top, #fbb450, #f89406); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); + background-image: -webkit-linear-gradient(top, #fbb450, #f89406); + background-image: -o-linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(to bottom, #fbb450, #f89406); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); + border-color: #f89406 #f89406 #ad6704; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #f89406; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.btn-warning:hover, +.btn-warning:focus, +.btn-warning:active, +.btn-warning.active, +.btn-warning.disabled, +.btn-warning[disabled] { + color: #ffffff; + background-color: #f89406; + *background-color: #df8505; +} +.btn-warning:active, +.btn-warning.active { + background-color: #c67605 \9; +} +.btn-danger { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #da4f49; + background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f); + background-image: -o-linear-gradient(top, #ee5f5b, #bd362f); + background-image: linear-gradient(to bottom, #ee5f5b, #bd362f); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0); + border-color: #bd362f #bd362f #802420; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #bd362f; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.btn-danger:hover, +.btn-danger:focus, +.btn-danger:active, +.btn-danger.active, +.btn-danger.disabled, +.btn-danger[disabled] { + color: #ffffff; + background-color: #bd362f; + *background-color: #a9302a; +} +.btn-danger:active, +.btn-danger.active { + background-color: #942a25 \9; +} +.btn-success { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #5bb75b; + background-image: -moz-linear-gradient(top, #62c462, #51a351); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351)); + background-image: -webkit-linear-gradient(top, #62c462, #51a351); + background-image: -o-linear-gradient(top, #62c462, #51a351); + background-image: linear-gradient(to bottom, #62c462, #51a351); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0); + border-color: #51a351 #51a351 #387038; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #51a351; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.btn-success:hover, +.btn-success:focus, +.btn-success:active, +.btn-success.active, +.btn-success.disabled, +.btn-success[disabled] { + color: #ffffff; + background-color: #51a351; + *background-color: #499249; +} +.btn-success:active, +.btn-success.active { + background-color: #408140 \9; +} +.btn-info { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #49afcd; + background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4)); + background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4); + background-image: -o-linear-gradient(top, #5bc0de, #2f96b4); + background-image: linear-gradient(to bottom, #5bc0de, #2f96b4); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0); + border-color: #2f96b4 #2f96b4 #1f6377; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #2f96b4; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.btn-info:hover, +.btn-info:focus, +.btn-info:active, +.btn-info.active, +.btn-info.disabled, +.btn-info[disabled] { + color: #ffffff; + background-color: #2f96b4; + *background-color: #2a85a0; +} +.btn-info:active, +.btn-info.active { + background-color: #24748c \9; +} +.btn-inverse { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #363636; + background-image: -moz-linear-gradient(top, #444444, #222222); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222)); + background-image: -webkit-linear-gradient(top, #444444, #222222); + background-image: -o-linear-gradient(top, #444444, #222222); + background-image: linear-gradient(to bottom, #444444, #222222); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0); + border-color: #222222 #222222 #000000; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #222222; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.btn-inverse:hover, +.btn-inverse:focus, +.btn-inverse:active, +.btn-inverse.active, +.btn-inverse.disabled, +.btn-inverse[disabled] { + color: #ffffff; + background-color: #222222; + *background-color: #151515; +} +.btn-inverse:active, +.btn-inverse.active { + background-color: #080808 \9; +} +button.btn, +input[type="submit"].btn { + *padding-top: 3px; + *padding-bottom: 3px; +} +button.btn::-moz-focus-inner, +input[type="submit"].btn::-moz-focus-inner { + padding: 0; + border: 0; +} +button.btn.btn-large, +input[type="submit"].btn.btn-large { + *padding-top: 7px; + *padding-bottom: 7px; +} +button.btn.btn-small, +input[type="submit"].btn.btn-small { + *padding-top: 3px; + *padding-bottom: 3px; +} +button.btn.btn-mini, +input[type="submit"].btn.btn-mini { + *padding-top: 1px; + *padding-bottom: 1px; +} +.btn-link, +.btn-link:active, +.btn-link[disabled] { + background-color: transparent; + background-image: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +.btn-link { + border-color: transparent; + cursor: pointer; + color: #0088cc; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.btn-link:hover, +.btn-link:focus { + color: #005580; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +.btn-link[disabled]:focus { + color: #333333; + text-decoration: none; +} +.btn-group { + position: relative; + display: inline-block; + *display: inline; + /* IE7 inline-block hack */ + *zoom: 1; + font-size: 0; + vertical-align: middle; + white-space: nowrap; + *margin-left: .3em; +} +.btn-group:first-child { + *margin-left: 0; +} +.btn-group + .btn-group { + margin-left: 5px; +} +.btn-toolbar { + font-size: 0; + margin-top: 10px; + margin-bottom: 10px; +} +.btn-toolbar > .btn + .btn, +.btn-toolbar > .btn-group + .btn, +.btn-toolbar > .btn + .btn-group { + margin-left: 5px; +} +.btn-group > .btn { + position: relative; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.btn-group > .btn + .btn { + margin-left: -1px; +} +.btn-group > .btn, +.btn-group > .dropdown-menu, +.btn-group > .popover { + font-size: 14px; +} +.btn-group > .btn-mini { + font-size: 10.5px; +} +.btn-group > .btn-small { + font-size: 11.9px; +} +.btn-group > .btn-large { + font-size: 17.5px; +} +.btn-group > .btn:first-child { + margin-left: 0; + -webkit-border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; + border-top-left-radius: 4px; + -webkit-border-bottom-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + border-bottom-left-radius: 4px; +} +.btn-group > .btn:last-child, +.btn-group > .dropdown-toggle { + -webkit-border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; + border-top-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -moz-border-radius-bottomright: 4px; + border-bottom-right-radius: 4px; +} +.btn-group > .btn.large:first-child { + margin-left: 0; + -webkit-border-top-left-radius: 6px; + -moz-border-radius-topleft: 6px; + border-top-left-radius: 6px; + -webkit-border-bottom-left-radius: 6px; + -moz-border-radius-bottomleft: 6px; + border-bottom-left-radius: 6px; +} +.btn-group > .btn.large:last-child, +.btn-group > .large.dropdown-toggle { + -webkit-border-top-right-radius: 6px; + -moz-border-radius-topright: 6px; + border-top-right-radius: 6px; + -webkit-border-bottom-right-radius: 6px; + -moz-border-radius-bottomright: 6px; + border-bottom-right-radius: 6px; +} +.btn-group > .btn:hover, +.btn-group > .btn:focus, +.btn-group > .btn:active, +.btn-group > .btn.active { + z-index: 2; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .btn + .dropdown-toggle { + padding-left: 8px; + padding-right: 8px; + -webkit-box-shadow: inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); + -moz-box-shadow: inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); + box-shadow: inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); + *padding-top: 5px; + *padding-bottom: 5px; +} +.btn-group > .btn-mini + .dropdown-toggle { + padding-left: 5px; + padding-right: 5px; + *padding-top: 2px; + *padding-bottom: 2px; +} +.btn-group > .btn-small + .dropdown-toggle { + *padding-top: 5px; + *padding-bottom: 4px; +} +.btn-group > .btn-large + .dropdown-toggle { + padding-left: 12px; + padding-right: 12px; + *padding-top: 7px; + *padding-bottom: 7px; +} +.btn-group.open .dropdown-toggle { + background-image: none; + -webkit-box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); + -moz-box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); + box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); +} +.btn-group.open .btn.dropdown-toggle { + background-color: #e6e6e6; +} +.btn-group.open .btn-primary.dropdown-toggle { + background-color: #0044cc; +} +.btn-group.open .btn-warning.dropdown-toggle { + background-color: #f89406; +} +.btn-group.open .btn-danger.dropdown-toggle { + background-color: #bd362f; +} +.btn-group.open .btn-success.dropdown-toggle { + background-color: #51a351; +} +.btn-group.open .btn-info.dropdown-toggle { + background-color: #2f96b4; +} +.btn-group.open .btn-inverse.dropdown-toggle { + background-color: #222222; +} +.btn .caret { + margin-top: 8px; + margin-left: 0; +} +.btn-large .caret { + margin-top: 6px; +} +.btn-large .caret { + border-left-width: 5px; + border-right-width: 5px; + border-top-width: 5px; +} +.btn-mini .caret, +.btn-small .caret { + margin-top: 8px; +} +.dropup .btn-large .caret { + border-bottom-width: 5px; +} +.btn-primary .caret, +.btn-warning .caret, +.btn-danger .caret, +.btn-info .caret, +.btn-success .caret, +.btn-inverse .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} +.btn-group-vertical { + display: inline-block; + *display: inline; + /* IE7 inline-block hack */ + *zoom: 1; +} +.btn-group-vertical > .btn { + display: block; + float: none; + max-width: 100%; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.btn-group-vertical > .btn + .btn { + margin-left: 0; + margin-top: -1px; +} +.btn-group-vertical > .btn:first-child { + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} +.btn-group-vertical > .btn:last-child { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} +.btn-group-vertical > .btn-large:first-child { + -webkit-border-radius: 6px 6px 0 0; + -moz-border-radius: 6px 6px 0 0; + border-radius: 6px 6px 0 0; +} +.btn-group-vertical > .btn-large:last-child { + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; +} +.alert { + padding: 8px 35px 8px 14px; + margin-bottom: 20px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + background-color: #fcf8e3; + border: 1px solid #fbeed5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.alert, +.alert h4 { + color: #c09853; +} +.alert h4 { + margin: 0; +} +.alert .close { + position: relative; + top: -2px; + right: -21px; + line-height: 20px; +} +.alert-success { + background-color: #dff0d8; + border-color: #d6e9c6; + color: #468847; +} +.alert-success h4 { + color: #468847; +} +.alert-danger, +.alert-error { + background-color: #f2dede; + border-color: #eed3d7; + color: #b94a48; +} +.alert-danger h4, +.alert-error h4 { + color: #b94a48; +} +.alert-info { + background-color: #d9edf7; + border-color: #bce8f1; + color: #3a87ad; +} +.alert-info h4 { + color: #3a87ad; +} +.alert-block { + padding-top: 14px; + padding-bottom: 14px; +} +.alert-block > p, +.alert-block > ul { + margin-bottom: 0; +} +.alert-block p + p { + margin-top: 5px; +} +.nav { + margin-left: 0; + margin-bottom: 20px; + list-style: none; +} +.nav > li > a { + display: block; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} +.nav > li > a > img { + max-width: none; +} +.nav > .pull-right { + float: right; +} +.nav-header { + display: block; + padding: 3px 15px; + font-size: 11px; + font-weight: bold; + line-height: 20px; + color: #999999; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-transform: uppercase; +} +.nav li + .nav-header { + margin-top: 9px; +} +.nav-list { + padding-left: 15px; + padding-right: 15px; + margin-bottom: 0; +} +.nav-list > li > a, +.nav-list .nav-header { + margin-left: -15px; + margin-right: -15px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); +} +.nav-list > li > a { + padding: 3px 15px; +} +.nav-list > .active > a, +.nav-list > .active > a:hover, +.nav-list > .active > a:focus { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); + background-color: #0088cc; +} +.nav-list [class^="icon-"], +.nav-list [class*=" icon-"] { + margin-right: 2px; +} +.nav-list .divider { + *width: 100%; + height: 1px; + margin: 9px 1px; + *margin: -5px 0 5px; + overflow: hidden; + background-color: #e5e5e5; + border-bottom: 1px solid #ffffff; +} +.nav-tabs, +.nav-pills { + *zoom: 1; +} +.nav-tabs:before, +.nav-pills:before, +.nav-tabs:after, +.nav-pills:after { + display: table; + content: ""; + line-height: 0; +} +.nav-tabs:after, +.nav-pills:after { + clear: both; +} +.nav-tabs > li, +.nav-pills > li { + float: left; +} +.nav-tabs > li > a, +.nav-pills > li > a { + padding-right: 12px; + padding-left: 12px; + margin-right: 2px; + line-height: 14px; +} +.nav-tabs { + border-bottom: 1px solid #ddd; +} +.nav-tabs > li { + margin-bottom: -1px; +} +.nav-tabs > li > a { + padding-top: 8px; + padding-bottom: 8px; + line-height: 20px; + border: 1px solid transparent; + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover, +.nav-tabs > li > a:focus { + border-color: #eeeeee #eeeeee #dddddd; +} +.nav-tabs > .active > a, +.nav-tabs > .active > a:hover, +.nav-tabs > .active > a:focus { + color: #555555; + background-color: #ffffff; + border: 1px solid #ddd; + border-bottom-color: transparent; + cursor: default; +} +.nav-pills > li > a { + padding-top: 8px; + padding-bottom: 8px; + margin-top: 2px; + margin-bottom: 2px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} +.nav-pills > .active > a, +.nav-pills > .active > a:hover, +.nav-pills > .active > a:focus { + color: #ffffff; + background-color: #0088cc; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li > a { + margin-right: 0; +} +.nav-tabs.nav-stacked { + border-bottom: 0; +} +.nav-tabs.nav-stacked > li > a { + border: 1px solid #ddd; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.nav-tabs.nav-stacked > li:first-child > a { + -webkit-border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; + border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; + border-top-left-radius: 4px; +} +.nav-tabs.nav-stacked > li:last-child > a { + -webkit-border-bottom-right-radius: 4px; + -moz-border-radius-bottomright: 4px; + border-bottom-right-radius: 4px; + -webkit-border-bottom-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + border-bottom-left-radius: 4px; +} +.nav-tabs.nav-stacked > li > a:hover, +.nav-tabs.nav-stacked > li > a:focus { + border-color: #ddd; + z-index: 2; +} +.nav-pills.nav-stacked > li > a { + margin-bottom: 3px; +} +.nav-pills.nav-stacked > li:last-child > a { + margin-bottom: 1px; +} +.nav-tabs .dropdown-menu { + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; +} +.nav-pills .dropdown-menu { + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} +.nav .dropdown-toggle .caret { + border-top-color: #0088cc; + border-bottom-color: #0088cc; + margin-top: 6px; +} +.nav .dropdown-toggle:hover .caret, +.nav .dropdown-toggle:focus .caret { + border-top-color: #005580; + border-bottom-color: #005580; +} +/* move down carets for tabs */ +.nav-tabs .dropdown-toggle .caret { + margin-top: 8px; +} +.nav .active .dropdown-toggle .caret { + border-top-color: #fff; + border-bottom-color: #fff; +} +.nav-tabs .active .dropdown-toggle .caret { + border-top-color: #555555; + border-bottom-color: #555555; +} +.nav > .dropdown.active > a:hover, +.nav > .dropdown.active > a:focus { + cursor: pointer; +} +.nav-tabs .open .dropdown-toggle, +.nav-pills .open .dropdown-toggle, +.nav > li.dropdown.open.active > a:hover, +.nav > li.dropdown.open.active > a:focus { + color: #ffffff; + background-color: #999999; + border-color: #999999; +} +.nav li.dropdown.open .caret, +.nav li.dropdown.open.active .caret, +.nav li.dropdown.open a:hover .caret, +.nav li.dropdown.open a:focus .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; + opacity: 1; + filter: alpha(opacity=100); +} +.tabs-stacked .open > a:hover, +.tabs-stacked .open > a:focus { + border-color: #999999; +} +.tabbable { + *zoom: 1; +} +.tabbable:before, +.tabbable:after { + display: table; + content: ""; + line-height: 0; +} +.tabbable:after { + clear: both; +} +.tab-content { + overflow: auto; +} +.tabs-below > .nav-tabs, +.tabs-right > .nav-tabs, +.tabs-left > .nav-tabs { + border-bottom: 0; +} +.tab-content > .tab-pane, +.pill-content > .pill-pane { + display: none; +} +.tab-content > .active, +.pill-content > .active { + display: block; +} +.tabs-below > .nav-tabs { + border-top: 1px solid #ddd; +} +.tabs-below > .nav-tabs > li { + margin-top: -1px; + margin-bottom: 0; +} +.tabs-below > .nav-tabs > li > a { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} +.tabs-below > .nav-tabs > li > a:hover, +.tabs-below > .nav-tabs > li > a:focus { + border-bottom-color: transparent; + border-top-color: #ddd; +} +.tabs-below > .nav-tabs > .active > a, +.tabs-below > .nav-tabs > .active > a:hover, +.tabs-below > .nav-tabs > .active > a:focus { + border-color: transparent #ddd #ddd #ddd; +} +.tabs-left > .nav-tabs > li, +.tabs-right > .nav-tabs > li { + float: none; +} +.tabs-left > .nav-tabs > li > a, +.tabs-right > .nav-tabs > li > a { + min-width: 74px; + margin-right: 0; + margin-bottom: 3px; +} +.tabs-left > .nav-tabs { + float: left; + margin-right: 19px; + border-right: 1px solid #ddd; +} +.tabs-left > .nav-tabs > li > a { + margin-right: -1px; + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} +.tabs-left > .nav-tabs > li > a:hover, +.tabs-left > .nav-tabs > li > a:focus { + border-color: #eeeeee #dddddd #eeeeee #eeeeee; +} +.tabs-left > .nav-tabs .active > a, +.tabs-left > .nav-tabs .active > a:hover, +.tabs-left > .nav-tabs .active > a:focus { + border-color: #ddd transparent #ddd #ddd; + *border-right-color: #ffffff; +} +.tabs-right > .nav-tabs { + float: right; + margin-left: 19px; + border-left: 1px solid #ddd; +} +.tabs-right > .nav-tabs > li > a { + margin-left: -1px; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} +.tabs-right > .nav-tabs > li > a:hover, +.tabs-right > .nav-tabs > li > a:focus { + border-color: #eeeeee #eeeeee #eeeeee #dddddd; +} +.tabs-right > .nav-tabs .active > a, +.tabs-right > .nav-tabs .active > a:hover, +.tabs-right > .nav-tabs .active > a:focus { + border-color: #ddd #ddd #ddd transparent; + *border-left-color: #ffffff; +} +.nav > .disabled > a { + color: #999999; +} +.nav > .disabled > a:hover, +.nav > .disabled > a:focus { + text-decoration: none; + background-color: transparent; + cursor: default; +} +.navbar { + overflow: visible; + margin-bottom: 20px; + *position: relative; + *z-index: 2; +} +.navbar-inner { + min-height: 40px; + padding-left: 20px; + padding-right: 20px; + background-color: #fafafa; + background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2)); + background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2); + background-image: -o-linear-gradient(top, #ffffff, #f2f2f2); + background-image: linear-gradient(to bottom, #ffffff, #f2f2f2); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0); + border: 1px solid #d4d4d4; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); + -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); + *zoom: 1; +} +.navbar-inner:before, +.navbar-inner:after { + display: table; + content: ""; + line-height: 0; +} +.navbar-inner:after { + clear: both; +} +.navbar .container { + width: auto; +} +.nav-collapse.collapse { + height: auto; + overflow: visible; +} +.navbar .brand { + float: left; + display: block; + padding: 10px 20px 10px; + margin-left: -20px; + font-size: 20px; + font-weight: 200; + color: #777777; + text-shadow: 0 1px 0 #ffffff; +} +.navbar .brand:hover, +.navbar .brand:focus { + text-decoration: none; +} +.navbar-text { + margin-bottom: 0; + line-height: 40px; + color: #777777; +} +.navbar-link { + color: #777777; +} +.navbar-link:hover, +.navbar-link:focus { + color: #333333; +} +.navbar .divider-vertical { + height: 40px; + margin: 0 9px; + border-left: 1px solid #f2f2f2; + border-right: 1px solid #ffffff; +} +.navbar .btn, +.navbar .btn-group { + margin-top: 5px; +} +.navbar .btn-group .btn, +.navbar .input-prepend .btn, +.navbar .input-append .btn, +.navbar .input-prepend .btn-group, +.navbar .input-append .btn-group { + margin-top: 0; +} +.navbar-form { + margin-bottom: 0; + *zoom: 1; +} +.navbar-form:before, +.navbar-form:after { + display: table; + content: ""; + line-height: 0; +} +.navbar-form:after { + clear: both; +} +.navbar-form input, +.navbar-form select, +.navbar-form .radio, +.navbar-form .checkbox { + margin-top: 5px; +} +.navbar-form input, +.navbar-form select, +.navbar-form .btn { + display: inline-block; + margin-bottom: 0; +} +.navbar-form input[type="image"], +.navbar-form input[type="checkbox"], +.navbar-form input[type="radio"] { + margin-top: 3px; +} +.navbar-form .input-append, +.navbar-form .input-prepend { + margin-top: 5px; + white-space: nowrap; +} +.navbar-form .input-append input, +.navbar-form .input-prepend input { + margin-top: 0; +} +.navbar-search { + position: relative; + float: left; + margin-top: 5px; + margin-bottom: 0; +} +.navbar-search .search-query { + margin-bottom: 0; + padding: 4px 14px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + font-weight: normal; + line-height: 1; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} +.navbar-static-top { + position: static; + margin-bottom: 0; +} +.navbar-static-top .navbar-inner { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; + margin-bottom: 0; +} +.navbar-fixed-top .navbar-inner, +.navbar-static-top .navbar-inner { + border-width: 0 0 1px; +} +.navbar-fixed-bottom .navbar-inner { + border-width: 1px 0 0; +} +.navbar-fixed-top .navbar-inner, +.navbar-fixed-bottom .navbar-inner { + padding-left: 0; + padding-right: 0; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.navbar-static-top .container, +.navbar-fixed-top .container, +.navbar-fixed-bottom .container { + width: 940px; +} +.navbar-fixed-top { + top: 0; +} +.navbar-fixed-top .navbar-inner, +.navbar-static-top .navbar-inner { + -webkit-box-shadow: 0 1px 10px rgba(0,0,0,.1); + -moz-box-shadow: 0 1px 10px rgba(0,0,0,.1); + box-shadow: 0 1px 10px rgba(0,0,0,.1); +} +.navbar-fixed-bottom { + bottom: 0; +} +.navbar-fixed-bottom .navbar-inner { + -webkit-box-shadow: 0 -1px 10px rgba(0,0,0,.1); + -moz-box-shadow: 0 -1px 10px rgba(0,0,0,.1); + box-shadow: 0 -1px 10px rgba(0,0,0,.1); +} +.navbar .nav { + position: relative; + left: 0; + display: block; + float: left; + margin: 0 10px 0 0; +} +.navbar .nav.pull-right { + float: right; + margin-right: 0; +} +.navbar .nav > li { + float: left; +} +.navbar .nav > li > a { + float: none; + padding: 10px 15px 10px; + color: #777777; + text-decoration: none; + text-shadow: 0 1px 0 #ffffff; +} +.navbar .nav .dropdown-toggle .caret { + margin-top: 8px; +} +.navbar .nav > li > a:focus, +.navbar .nav > li > a:hover { + background-color: transparent; + color: #333333; + text-decoration: none; +} +.navbar .nav > .active > a, +.navbar .nav > .active > a:hover, +.navbar .nav > .active > a:focus { + color: #555555; + text-decoration: none; + background-color: #e5e5e5; + -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); + -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); +} +.navbar .btn-navbar { + display: none; + float: right; + padding: 7px 10px; + margin-left: 5px; + margin-right: 5px; + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #ededed; + background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5)); + background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0); + border-color: #e5e5e5 #e5e5e5 #bfbfbf; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #e5e5e5; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075); + -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075); + box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075); +} +.navbar .btn-navbar:hover, +.navbar .btn-navbar:focus, +.navbar .btn-navbar:active, +.navbar .btn-navbar.active, +.navbar .btn-navbar.disabled, +.navbar .btn-navbar[disabled] { + color: #ffffff; + background-color: #e5e5e5; + *background-color: #d9d9d9; +} +.navbar .btn-navbar:active, +.navbar .btn-navbar.active { + background-color: #cccccc \9; +} +.navbar .btn-navbar .icon-bar { + display: block; + width: 18px; + height: 2px; + background-color: #f5f5f5; + -webkit-border-radius: 1px; + -moz-border-radius: 1px; + border-radius: 1px; + -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); +} +.btn-navbar .icon-bar + .icon-bar { + margin-top: 3px; +} +.navbar .nav > li > .dropdown-menu:before { + content: ''; + display: inline-block; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-bottom-color: rgba(0, 0, 0, 0.2); + position: absolute; + top: -7px; + left: 9px; +} +.navbar .nav > li > .dropdown-menu:after { + content: ''; + display: inline-block; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid #ffffff; + position: absolute; + top: -6px; + left: 10px; +} +.navbar-fixed-bottom .nav > li > .dropdown-menu:before { + border-top: 7px solid #ccc; + border-top-color: rgba(0, 0, 0, 0.2); + border-bottom: 0; + bottom: -7px; + top: auto; +} +.navbar-fixed-bottom .nav > li > .dropdown-menu:after { + border-top: 6px solid #ffffff; + border-bottom: 0; + bottom: -6px; + top: auto; +} +.navbar .nav li.dropdown > a:hover .caret, +.navbar .nav li.dropdown > a:focus .caret { + border-top-color: #333333; + border-bottom-color: #333333; +} +.navbar .nav li.dropdown.open > .dropdown-toggle, +.navbar .nav li.dropdown.active > .dropdown-toggle, +.navbar .nav li.dropdown.open.active > .dropdown-toggle { + background-color: #e5e5e5; + color: #555555; +} +.navbar .nav li.dropdown > .dropdown-toggle .caret { + border-top-color: #777777; + border-bottom-color: #777777; +} +.navbar .nav li.dropdown.open > .dropdown-toggle .caret, +.navbar .nav li.dropdown.active > .dropdown-toggle .caret, +.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret { + border-top-color: #555555; + border-bottom-color: #555555; +} +.navbar .pull-right > li > .dropdown-menu, +.navbar .nav > li > .dropdown-menu.pull-right { + left: auto; + right: 0; +} +.navbar .pull-right > li > .dropdown-menu:before, +.navbar .nav > li > .dropdown-menu.pull-right:before { + left: auto; + right: 12px; +} +.navbar .pull-right > li > .dropdown-menu:after, +.navbar .nav > li > .dropdown-menu.pull-right:after { + left: auto; + right: 13px; +} +.navbar .pull-right > li > .dropdown-menu .dropdown-menu, +.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu { + left: auto; + right: 100%; + margin-left: 0; + margin-right: -1px; + -webkit-border-radius: 6px 0 6px 6px; + -moz-border-radius: 6px 0 6px 6px; + border-radius: 6px 0 6px 6px; +} +.navbar-inverse .navbar-inner { + background-color: #1b1b1b; + background-image: -moz-linear-gradient(top, #222222, #111111); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111)); + background-image: -webkit-linear-gradient(top, #222222, #111111); + background-image: -o-linear-gradient(top, #222222, #111111); + background-image: linear-gradient(to bottom, #222222, #111111); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0); + border-color: #252525; +} +.navbar-inverse .brand, +.navbar-inverse .nav > li > a { + color: #999999; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.navbar-inverse .brand:hover, +.navbar-inverse .nav > li > a:hover, +.navbar-inverse .brand:focus, +.navbar-inverse .nav > li > a:focus { + color: #ffffff; +} +.navbar-inverse .brand { + color: #999999; +} +.navbar-inverse .navbar-text { + color: #999999; +} +.navbar-inverse .nav > li > a:focus, +.navbar-inverse .nav > li > a:hover { + background-color: transparent; + color: #ffffff; +} +.navbar-inverse .nav .active > a, +.navbar-inverse .nav .active > a:hover, +.navbar-inverse .nav .active > a:focus { + color: #ffffff; + background-color: #111111; +} +.navbar-inverse .navbar-link { + color: #999999; +} +.navbar-inverse .navbar-link:hover, +.navbar-inverse .navbar-link:focus { + color: #ffffff; +} +.navbar-inverse .divider-vertical { + border-left-color: #111111; + border-right-color: #222222; +} +.navbar-inverse .nav li.dropdown.open > .dropdown-toggle, +.navbar-inverse .nav li.dropdown.active > .dropdown-toggle, +.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle { + background-color: #111111; + color: #ffffff; +} +.navbar-inverse .nav li.dropdown > a:hover .caret, +.navbar-inverse .nav li.dropdown > a:focus .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} +.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret { + border-top-color: #999999; + border-bottom-color: #999999; +} +.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret, +.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret, +.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} +.navbar-inverse .navbar-search .search-query { + color: #ffffff; + background-color: #515151; + border-color: #111111; + -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15); + -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15); + box-shadow: inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15); + -webkit-transition: none; + -moz-transition: none; + -o-transition: none; + transition: none; +} +.navbar-inverse .navbar-search .search-query:-moz-placeholder { + color: #cccccc; +} +.navbar-inverse .navbar-search .search-query:-ms-input-placeholder { + color: #cccccc; +} +.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder { + color: #cccccc; +} +.navbar-inverse .navbar-search .search-query:focus, +.navbar-inverse .navbar-search .search-query.focused { + padding: 5px 15px; + color: #333333; + text-shadow: 0 1px 0 #ffffff; + background-color: #ffffff; + border: 0; + -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + outline: 0; +} +.navbar-inverse .btn-navbar { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #0e0e0e; + background-image: -moz-linear-gradient(top, #151515, #040404); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404)); + background-image: -webkit-linear-gradient(top, #151515, #040404); + background-image: -o-linear-gradient(top, #151515, #040404); + background-image: linear-gradient(to bottom, #151515, #040404); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0); + border-color: #040404 #040404 #000000; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #040404; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.navbar-inverse .btn-navbar:hover, +.navbar-inverse .btn-navbar:focus, +.navbar-inverse .btn-navbar:active, +.navbar-inverse .btn-navbar.active, +.navbar-inverse .btn-navbar.disabled, +.navbar-inverse .btn-navbar[disabled] { + color: #ffffff; + background-color: #040404; + *background-color: #000000; +} +.navbar-inverse .btn-navbar:active, +.navbar-inverse .btn-navbar.active { + background-color: #000000 \9; +} +.breadcrumb { + padding: 8px 15px; + margin: 0 0 20px; + list-style: none; + background-color: #f5f5f5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.breadcrumb > li { + display: inline-block; + *display: inline; + /* IE7 inline-block hack */ + *zoom: 1; + text-shadow: 0 1px 0 #ffffff; +} +.breadcrumb > li > .divider { + padding: 0 5px; + color: #ccc; +} +.breadcrumb > .active { + color: #999999; +} +.pagination { + margin: 20px 0; +} +.pagination ul { + display: inline-block; + *display: inline; + /* IE7 inline-block hack */ + *zoom: 1; + margin-left: 0; + margin-bottom: 0; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); +} +.pagination ul > li { + display: inline; +} +.pagination ul > li > a, +.pagination ul > li > span { + float: left; + padding: 4px 12px; + line-height: 20px; + text-decoration: none; + background-color: #ffffff; + border: 1px solid #dddddd; + border-left-width: 0; +} +.pagination ul > li > a:hover, +.pagination ul > li > a:focus, +.pagination ul > .active > a, +.pagination ul > .active > span { + background-color: #f5f5f5; +} +.pagination ul > .active > a, +.pagination ul > .active > span { + color: #999999; + cursor: default; +} +.pagination ul > .disabled > span, +.pagination ul > .disabled > a, +.pagination ul > .disabled > a:hover, +.pagination ul > .disabled > a:focus { + color: #999999; + background-color: transparent; + cursor: default; +} +.pagination ul > li:first-child > a, +.pagination ul > li:first-child > span { + border-left-width: 1px; + -webkit-border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; + border-top-left-radius: 4px; + -webkit-border-bottom-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + border-bottom-left-radius: 4px; +} +.pagination ul > li:last-child > a, +.pagination ul > li:last-child > span { + -webkit-border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; + border-top-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -moz-border-radius-bottomright: 4px; + border-bottom-right-radius: 4px; +} +.pagination-centered { + text-align: center; +} +.pagination-right { + text-align: right; +} +.pagination-large ul > li > a, +.pagination-large ul > li > span { + padding: 11px 19px; + font-size: 17.5px; +} +.pagination-large ul > li:first-child > a, +.pagination-large ul > li:first-child > span { + -webkit-border-top-left-radius: 6px; + -moz-border-radius-topleft: 6px; + border-top-left-radius: 6px; + -webkit-border-bottom-left-radius: 6px; + -moz-border-radius-bottomleft: 6px; + border-bottom-left-radius: 6px; +} +.pagination-large ul > li:last-child > a, +.pagination-large ul > li:last-child > span { + -webkit-border-top-right-radius: 6px; + -moz-border-radius-topright: 6px; + border-top-right-radius: 6px; + -webkit-border-bottom-right-radius: 6px; + -moz-border-radius-bottomright: 6px; + border-bottom-right-radius: 6px; +} +.pagination-mini ul > li:first-child > a, +.pagination-small ul > li:first-child > a, +.pagination-mini ul > li:first-child > span, +.pagination-small ul > li:first-child > span { + -webkit-border-top-left-radius: 3px; + -moz-border-radius-topleft: 3px; + border-top-left-radius: 3px; + -webkit-border-bottom-left-radius: 3px; + -moz-border-radius-bottomleft: 3px; + border-bottom-left-radius: 3px; +} +.pagination-mini ul > li:last-child > a, +.pagination-small ul > li:last-child > a, +.pagination-mini ul > li:last-child > span, +.pagination-small ul > li:last-child > span { + -webkit-border-top-right-radius: 3px; + -moz-border-radius-topright: 3px; + border-top-right-radius: 3px; + -webkit-border-bottom-right-radius: 3px; + -moz-border-radius-bottomright: 3px; + border-bottom-right-radius: 3px; +} +.pagination-small ul > li > a, +.pagination-small ul > li > span { + padding: 2px 10px; + font-size: 11.9px; +} +.pagination-mini ul > li > a, +.pagination-mini ul > li > span { + padding: 0 6px; + font-size: 10.5px; +} +.pager { + margin: 20px 0; + list-style: none; + text-align: center; + *zoom: 1; +} +.pager:before, +.pager:after { + display: table; + content: ""; + line-height: 0; +} +.pager:after { + clear: both; +} +.pager li { + display: inline; +} +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #f5f5f5; +} +.pager .next > a, +.pager .next > span { + float: right; +} +.pager .previous > a, +.pager .previous > span { + float: left; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #999999; + background-color: #fff; + cursor: default; +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000000; +} +.modal-backdrop.fade { + opacity: 0; +} +.modal-backdrop, +.modal-backdrop.fade.in { + opacity: 0.8; + filter: alpha(opacity=80); +} +.modal { + position: fixed; + top: 10%; + left: 50%; + z-index: 1050; + width: 560px; + margin-left: -280px; + background-color: #ffffff; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.3); + *border: 1px solid #999; + /* IE6-7 */ + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; + outline: none; +} +.modal.fade { + -webkit-transition: opacity .3s linear, top .3s ease-out; + -moz-transition: opacity .3s linear, top .3s ease-out; + -o-transition: opacity .3s linear, top .3s ease-out; + transition: opacity .3s linear, top .3s ease-out; + top: -25%; +} +.modal.fade.in { + top: 10%; +} +.modal-header { + padding: 9px 15px; + border-bottom: 1px solid #eee; +} +.modal-header .close { + margin-top: 2px; +} +.modal-header h3 { + margin: 0; + line-height: 30px; +} +.modal-body { + position: relative; + overflow-y: auto; + max-height: 400px; + padding: 15px; +} +.modal-form { + margin-bottom: 0; +} +.modal-footer { + padding: 14px 15px 15px; + margin-bottom: 0; + text-align: right; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; + *zoom: 1; +} +.modal-footer:before, +.modal-footer:after { + display: table; + content: ""; + line-height: 0; +} +.modal-footer:after { + clear: both; +} +.modal-footer .btn + .btn { + margin-left: 5px; + margin-bottom: 0; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.tooltip { + position: absolute; + z-index: 1030; + display: block; + visibility: visible; + font-size: 11px; + line-height: 1.4; + opacity: 0; + filter: alpha(opacity=0); +} +.tooltip.in { + opacity: 0.8; + filter: alpha(opacity=80); +} +.tooltip.top { + margin-top: -3px; + padding: 5px 0; +} +.tooltip.right { + margin-left: 3px; + padding: 0 5px; +} +.tooltip.bottom { + margin-top: 3px; + padding: 5px 0; +} +.tooltip.left { + margin-left: -3px; + padding: 0 5px; +} +.tooltip-inner { + max-width: 200px; + padding: 8px; + color: #ffffff; + text-align: center; + text-decoration: none; + background-color: #000000; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1010; + display: none; + max-width: 276px; + padding: 1px; + text-align: left; + background-color: #ffffff; + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + white-space: normal; +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + margin: 0; + padding: 8px 14px; + font-size: 14px; + font-weight: normal; + line-height: 18px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + -webkit-border-radius: 5px 5px 0 0; + -moz-border-radius: 5px 5px 0 0; + border-radius: 5px 5px 0 0; +} +.popover-title:empty { + display: none; +} +.popover-content { + padding: 9px 14px; +} +.popover .arrow, +.popover .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover .arrow { + border-width: 11px; +} +.popover .arrow:after { + border-width: 10px; + content: ""; +} +.popover.top .arrow { + left: 50%; + margin-left: -11px; + border-bottom-width: 0; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, 0.25); + bottom: -11px; +} +.popover.top .arrow:after { + bottom: 1px; + margin-left: -10px; + border-bottom-width: 0; + border-top-color: #ffffff; +} +.popover.right .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-left-width: 0; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, 0.25); +} +.popover.right .arrow:after { + left: 1px; + bottom: -10px; + border-left-width: 0; + border-right-color: #ffffff; +} +.popover.bottom .arrow { + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, 0.25); + top: -11px; +} +.popover.bottom .arrow:after { + top: 1px; + margin-left: -10px; + border-top-width: 0; + border-bottom-color: #ffffff; +} +.popover.left .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, 0.25); +} +.popover.left .arrow:after { + right: 1px; + border-right-width: 0; + border-left-color: #ffffff; + bottom: -10px; +} +.thumbnails { + margin-left: -20px; + list-style: none; + *zoom: 1; +} +.thumbnails:before, +.thumbnails:after { + display: table; + content: ""; + line-height: 0; +} +.thumbnails:after { + clear: both; +} +.row-fluid .thumbnails { + margin-left: 0; +} +.thumbnails > li { + float: left; + margin-bottom: 20px; + margin-left: 20px; +} +.thumbnail { + display: block; + padding: 4px; + line-height: 20px; + border: 1px solid #ddd; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + -webkit-transition: all 0.2s ease-in-out; + -moz-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; +} +a.thumbnail:hover, +a.thumbnail:focus { + border-color: #0088cc; + -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); +} +.thumbnail > img { + display: block; + max-width: 100%; + margin-left: auto; + margin-right: auto; +} +.thumbnail .caption { + padding: 9px; + color: #555555; +} +.media, +.media-body { + overflow: hidden; + *overflow: visible; + zoom: 1; +} +.media, +.media .media { + margin-top: 15px; +} +.media:first-child { + margin-top: 0; +} +.media-object { + display: block; +} +.media-heading { + margin: 0 0 5px; +} +.media > .pull-left { + margin-right: 10px; +} +.media > .pull-right { + margin-left: 10px; +} +.media-list { + margin-left: 0; + list-style: none; +} +.label, +.badge { + display: inline-block; + padding: 2px 4px; + font-size: 11.844px; + font-weight: bold; + line-height: 14px; + color: #ffffff; + vertical-align: baseline; + white-space: nowrap; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #999999; +} +.label { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} +.badge { + padding-left: 9px; + padding-right: 9px; + -webkit-border-radius: 9px; + -moz-border-radius: 9px; + border-radius: 9px; +} +.label:empty, +.badge:empty { + display: none; +} +a.label:hover, +a.label:focus, +a.badge:hover, +a.badge:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} +.label-important, +.badge-important { + background-color: #b94a48; +} +.label-important[href], +.badge-important[href] { + background-color: #953b39; +} +.label-warning, +.badge-warning { + background-color: #f89406; +} +.label-warning[href], +.badge-warning[href] { + background-color: #c67605; +} +.label-success, +.badge-success { + background-color: #468847; +} +.label-success[href], +.badge-success[href] { + background-color: #356635; +} +.label-info, +.badge-info { + background-color: #3a87ad; +} +.label-info[href], +.badge-info[href] { + background-color: #2d6987; +} +.label-inverse, +.badge-inverse { + background-color: #333333; +} +.label-inverse[href], +.badge-inverse[href] { + background-color: #1a1a1a; +} +.btn .label, +.btn .badge { + position: relative; + top: -1px; +} +.btn-mini .label, +.btn-mini .badge { + top: 0; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@-moz-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@-ms-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@-o-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + overflow: hidden; + height: 20px; + margin-bottom: 20px; + background-color: #f7f7f7; + background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); + background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0); + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.progress .bar { + width: 0%; + height: 100%; + color: #ffffff; + float: left; + font-size: 12px; + text-align: center; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #0e90d2; + background-image: -moz-linear-gradient(top, #149bdf, #0480be); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); + background-image: -webkit-linear-gradient(top, #149bdf, #0480be); + background-image: -o-linear-gradient(top, #149bdf, #0480be); + background-image: linear-gradient(to bottom, #149bdf, #0480be); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0); + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-transition: width 0.6s ease; + -moz-transition: width 0.6s ease; + -o-transition: width 0.6s ease; + transition: width 0.6s ease; +} +.progress .bar + .bar { + -webkit-box-shadow: inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15); + -moz-box-shadow: inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15); + box-shadow: inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15); +} +.progress-striped .bar { + background-color: #149bdf; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + -moz-background-size: 40px 40px; + -o-background-size: 40px 40px; + background-size: 40px 40px; +} +.progress.active .bar { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -moz-animation: progress-bar-stripes 2s linear infinite; + -ms-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-danger .bar, +.progress .bar-danger { + background-color: #dd514c; + background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); + background-image: linear-gradient(to bottom, #ee5f5b, #c43c35); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0); +} +.progress-danger.progress-striped .bar, +.progress-striped .bar-danger { + background-color: #ee5f5b; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-success .bar, +.progress .bar-success { + background-color: #5eb95e; + background-image: -moz-linear-gradient(top, #62c462, #57a957); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); + background-image: -webkit-linear-gradient(top, #62c462, #57a957); + background-image: -o-linear-gradient(top, #62c462, #57a957); + background-image: linear-gradient(to bottom, #62c462, #57a957); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0); +} +.progress-success.progress-striped .bar, +.progress-striped .bar-success { + background-color: #62c462; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-info .bar, +.progress .bar-info { + background-color: #4bb1cf; + background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); + background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); + background-image: -o-linear-gradient(top, #5bc0de, #339bb9); + background-image: linear-gradient(to bottom, #5bc0de, #339bb9); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0); +} +.progress-info.progress-striped .bar, +.progress-striped .bar-info { + background-color: #5bc0de; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-warning .bar, +.progress .bar-warning { + background-color: #faa732; + background-image: -moz-linear-gradient(top, #fbb450, #f89406); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); + background-image: -webkit-linear-gradient(top, #fbb450, #f89406); + background-image: -o-linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(to bottom, #fbb450, #f89406); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); +} +.progress-warning.progress-striped .bar, +.progress-striped .bar-warning { + background-color: #fbb450; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.accordion { + margin-bottom: 20px; +} +.accordion-group { + margin-bottom: 2px; + border: 1px solid #e5e5e5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.accordion-heading { + border-bottom: 0; +} +.accordion-heading .accordion-toggle { + display: block; + padding: 8px 15px; +} +.accordion-toggle { + cursor: pointer; +} +.accordion-inner { + padding: 9px 15px; + border-top: 1px solid #e5e5e5; +} +.carousel { + position: relative; + margin-bottom: 20px; + line-height: 1; +} +.carousel-inner { + overflow: hidden; + width: 100%; + position: relative; +} +.carousel-inner > .item { + display: none; + position: relative; + -webkit-transition: 0.6s ease-in-out left; + -moz-transition: 0.6s ease-in-out left; + -o-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + line-height: 1; +} +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +.carousel-inner > .active { + left: 0; +} +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel-inner > .next { + left: 100%; +} +.carousel-inner > .prev { + left: -100%; +} +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +.carousel-inner > .active.left { + left: -100%; +} +.carousel-inner > .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 40%; + left: 15px; + width: 40px; + height: 40px; + margin-top: -20px; + font-size: 60px; + font-weight: 100; + line-height: 30px; + color: #ffffff; + text-align: center; + background: #222222; + border: 3px solid #ffffff; + -webkit-border-radius: 23px; + -moz-border-radius: 23px; + border-radius: 23px; + opacity: 0.5; + filter: alpha(opacity=50); +} +.carousel-control.right { + left: auto; + right: 15px; +} +.carousel-control:hover, +.carousel-control:focus { + color: #ffffff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); +} +.carousel-indicators { + position: absolute; + top: 15px; + right: 15px; + z-index: 5; + margin: 0; + list-style: none; +} +.carousel-indicators li { + display: block; + float: left; + width: 10px; + height: 10px; + margin-left: 5px; + text-indent: -999px; + background-color: #ccc; + background-color: rgba(255, 255, 255, 0.25); + border-radius: 5px; +} +.carousel-indicators .active { + background-color: #fff; +} +.carousel-caption { + position: absolute; + left: 0; + right: 0; + bottom: 0; + padding: 15px; + background: #333333; + background: rgba(0, 0, 0, 0.75); +} +.carousel-caption h4, +.carousel-caption p { + color: #ffffff; + line-height: 20px; +} +.carousel-caption h4 { + margin: 0 0 5px; +} +.carousel-caption p { + margin-bottom: 0; +} +.hero-unit { + padding: 60px; + margin-bottom: 30px; + font-size: 18px; + font-weight: 200; + line-height: 30px; + color: inherit; + background-color: #eeeeee; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} +.hero-unit h1 { + margin-bottom: 0; + font-size: 60px; + line-height: 1; + color: inherit; + letter-spacing: -1px; +} +.hero-unit li { + line-height: 30px; +} +.pull-right { + float: right; +} +.pull-left { + float: left; +} +.hide { + display: none; +} +.show { + display: block; +} +.invisible { + visibility: hidden; +} +.affix { + position: fixed; +} + diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/exception/DeviceCodeExpiredException.java b/openid-connect-server/src/main/java/org/mitre/oauth2/exception/DeviceCodeExpiredException.java new file mode 100644 index 0000000000..6444f184a4 --- /dev/null +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/exception/DeviceCodeExpiredException.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright 2017 The MITRE Corporation + * and the MIT Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +package org.mitre.oauth2.exception; + +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; + +/** + * @author jricher + * + */ +public class DeviceCodeExpiredException extends OAuth2Exception { + + /** + * @param msg + */ + public DeviceCodeExpiredException(String msg) { + super(msg); + } + + /** + * + */ + private static final long serialVersionUID = -7078098692596870940L; + + /* (non-Javadoc) + * @see org.springframework.security.oauth2.common.exceptions.OAuth2Exception#getOAuth2ErrorCode() + */ + @Override + public String getOAuth2ErrorCode() { + return "expired_token"; + } + +} diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/InMemoryDeviceCodeService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/InMemoryDeviceCodeService.java new file mode 100644 index 0000000000..eb522c5b69 --- /dev/null +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/InMemoryDeviceCodeService.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright 2017 The MITRE Corporation + * and the MIT Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +package org.mitre.oauth2.service.impl; + +import java.util.Date; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.mitre.oauth2.model.AuthenticationHolderEntity; +import org.mitre.oauth2.model.ClientDetailsEntity; +import org.mitre.oauth2.model.DeviceCode; +import org.mitre.oauth2.service.DeviceCodeService; +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.stereotype.Service; + +/** + * @author jricher + * + */ +@Service +public class InMemoryDeviceCodeService implements DeviceCodeService { + + private Set codes = new HashSet<>(); + + /* (non-Javadoc) + * @see org.mitre.oauth2.service.DeviceCodeService#save(org.mitre.oauth2.model.DeviceCode) + */ + @Override + public DeviceCode createNewDeviceCode(String deviceCode, String userCode, Set requestedScopes, ClientDetailsEntity client, Map parameters) { + + DeviceCode dc = new DeviceCode(deviceCode, userCode, requestedScopes, client.getClientId(), parameters); + + if (client.getDeviceCodeValiditySeconds() != null) { + dc.setExpiration(new Date(System.currentTimeMillis() + client.getDeviceCodeValiditySeconds() * 1000L)); + } + + dc.setApproved(false); + + codes.add(dc); + return dc; + } + + /* (non-Javadoc) + * @see org.mitre.oauth2.service.DeviceCodeService#lookUpByUserCode(java.lang.String) + */ + @Override + public DeviceCode lookUpByUserCode(String userCode) { + for (DeviceCode dc : codes) { + if (dc.getUserCode().equals(userCode)) { + return dc; + } + } + return null; + } + + /* (non-Javadoc) + * @see org.mitre.oauth2.service.DeviceCodeService#approveDeviceCode(org.mitre.oauth2.model.DeviceCode) + */ + @Override + public DeviceCode approveDeviceCode(DeviceCode dc, OAuth2Authentication auth) { + dc.setApproved(true); + + AuthenticationHolderEntity authHolder = new AuthenticationHolderEntity(); + authHolder.setAuthentication(auth); + dc.setAuthenticationHolder(authHolder); + + return dc; + } + + /* (non-Javadoc) + * @see org.mitre.oauth2.service.DeviceCodeService#consumeDeviceCode(java.lang.String, org.springframework.security.oauth2.provider.ClientDetails) + */ + @Override + public DeviceCode consumeDeviceCode(String deviceCode, ClientDetails client) { + for (DeviceCode dc : codes) { + if (dc.getDeviceCode().equals(deviceCode) && dc.getClientId().equals(client.getClientId())) { + codes.remove(dc); + return dc; + } + } + return null; + } + +} diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/token/DeviceTokenGranter.java b/openid-connect-server/src/main/java/org/mitre/oauth2/token/DeviceTokenGranter.java index f8252cab7a..7a47aa19ba 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/token/DeviceTokenGranter.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/token/DeviceTokenGranter.java @@ -17,7 +17,10 @@ package org.mitre.oauth2.token; +import java.util.Date; + import org.mitre.oauth2.exception.AuthorizationPendingException; +import org.mitre.oauth2.exception.DeviceCodeExpiredException; import org.mitre.oauth2.model.DeviceCode; import org.mitre.oauth2.service.DeviceCodeService; import org.mitre.oauth2.web.DeviceEndpoint; @@ -71,18 +74,23 @@ protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, Tok if (dc != null) { - if (dc.isApproved()) { + // make sure the code hasn't expired yet + if (dc.getExpiration() != null && dc.getExpiration().before(new Date())) { + // TODO: return an error + throw new DeviceCodeExpiredException("Device code has expired " + deviceCode); + + } else if (!dc.isApproved()) { + + // still waiting for approval + throw new AuthorizationPendingException("Authorization pending for code " + deviceCode); + } else { // inherit the (approved) scopes from the original request tokenRequest.setScope(dc.getScope()); OAuth2Authentication auth = new OAuth2Authentication(getRequestFactory().createOAuth2Request(client, tokenRequest), dc.getAuthenticationHolder().getUserAuth()); return auth; - } else { - - // still waiting for approval - throw new AuthorizationPendingException("Authorization pending for code " + deviceCode); } } else { throw new InvalidGrantException("Invalid device code: " + deviceCode); diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java index 975f0b0737..31028ef447 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java @@ -18,6 +18,7 @@ package org.mitre.oauth2.web; import java.util.Collection; +import java.util.Date; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; @@ -144,17 +145,15 @@ public String requestDeviceCode(@RequestParam("client_id") String clientId, @Req // create a user code, should be random but small and typable String userCode = randomGenerator.generate(); - // TODO: expiration + DeviceCode dc = deviceCodeService.createNewDeviceCode(deviceCode, userCode, requestedScopes, client, parameters); + model.put(JsonEntityView.ENTITY, ImmutableMap.of( "device_code", deviceCode, "user_code", userCode, - "verification_uri", config.getIssuer() + URL + "verification_uri", config.getIssuer() + URL, + "expires_in", client.getDeviceCodeValiditySeconds() )); - DeviceCode dc = new DeviceCode(deviceCode, userCode, requestedScopes, clientId, parameters); - - - deviceCodeService.save(dc); return JsonEntityView.VIEWNAME; @@ -177,6 +176,24 @@ public String readUserCode(@RequestParam("user_code") String userCode, ModelMap // look up the request based on the user code DeviceCode dc = deviceCodeService.lookUpByUserCode(userCode); + // we couldn't find the device code + if (dc == null) { + // TODO: return error + return "error"; + } + + // make sure the code hasn't expired yet + if (dc.getExpiration() != null && dc.getExpiration().before(new Date())) { + // TODO: return an error + return "error"; + } + + // make sure the device code hasn't already been approved + if (dc.isApproved()) { + // TODO: return an error + return "error"; + } + ClientDetailsEntity client = clientService.loadClientByClientId(dc.getClientId()); model.put("client", client); @@ -210,16 +227,30 @@ public String readUserCode(@RequestParam("user_code") String userCode, ModelMap @PreAuthorize("hasRole('ROLE_USER')") @RequestMapping(value = "/" + USER_URL + "/approve", method = RequestMethod.POST) - public String approveDevice(@RequestParam("user_code") String userCode, @RequestParam(value = "user_oauth_approval") String approve, ModelMap model, Authentication auth, HttpSession session) { + public String approveDevice(@RequestParam("user_code") String userCode, @RequestParam(value = "user_oauth_approval") Boolean approve, ModelMap model, Authentication auth, HttpSession session) { AuthorizationRequest authorizationRequest = (AuthorizationRequest) session.getAttribute("authorizationRequest"); DeviceCode dc = (DeviceCode) session.getAttribute("deviceCode"); + // make sure the form that was submitted is the one that we were expecting if (!dc.getUserCode().equals(userCode)) { // TODO: return an error return "error"; } + // make sure the code hasn't expired yet + if (dc.getExpiration() != null && dc.getExpiration().before(new Date())) { + // TODO: return an error + return "error"; + } + + // user did not approve + if (!approve) { + // TODO: return an error + return "error"; + } + + // create an OAuth request for storage OAuth2Request o2req = oAuth2RequestFactory.createOAuth2Request(authorizationRequest); OAuth2Authentication o2Auth = new OAuth2Authentication(o2req, auth); From 04dd67d073f5f13d1b1297118d9feb72f145e3b1 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Sat, 11 Mar 2017 15:29:24 -0500 Subject: [PATCH 343/465] added device codes to database --- .../db/hsql/hsql_database_tables.sql | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql b/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql index bf8e827f91..8f5e69ce7c 100644 --- a/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql +++ b/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql @@ -360,6 +360,26 @@ CREATE TABLE IF NOT EXISTS saved_registered_client ( registered_client VARCHAR(8192) ); +CREATE TABLE IF NOT EXISTS device_code ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) PRIMARY KEY, + device_code VARCHAR(1024), + user_code VARCHAR(1024), + expiration TIMESTAMP, + client_id VARCHAR(256), + approved BOOLEAN, + auth_holder_id BIGINT +); + +CREATE TABLE IF NOT EXISTS device_code_scope ( + owner_id BIGINT NOT NULL, + scope VARCHAR(256) NOT NULL +); + +CREATE TABLE IF NOT EXISTS device_code_request_parameter ( + owner_id BIGINT, + param VARCHAR(2048), + val VARCHAR(2048) +); CREATE INDEX at_tv_idx ON access_token(token_value); CREATE INDEX ts_oi_idx ON token_scope(owner_id); From 44b24af4662d970cec4172bfd046aaa237cc106c Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Sat, 11 Mar 2017 17:19:55 -0500 Subject: [PATCH 344/465] database storage for device flow --- .../org/mitre/oauth2/model/DeviceCode.java | 15 +++ .../repository/impl/DeviceCodeRepository.java | 59 ++++++++++++ .../db/hsql/hsql_database_tables.sql | 2 +- .../impl/JpaDeviceCodeRepository.java | 96 +++++++++++++++++++ ...ice.java => DefaultDeviceCodeService.java} | 48 +++++----- .../org/mitre/oauth2/web/DeviceEndpoint.java | 16 ++-- 6 files changed, 207 insertions(+), 29 deletions(-) create mode 100644 openid-connect-common/src/main/java/org/mitre/oauth2/repository/impl/DeviceCodeRepository.java create mode 100644 openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaDeviceCodeRepository.java rename openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/{InMemoryDeviceCodeService.java => DefaultDeviceCodeService.java} (75%) diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/DeviceCode.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/DeviceCode.java index 8f7486b9fe..a886729c30 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/DeviceCode.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/DeviceCode.java @@ -33,6 +33,8 @@ import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.MapKeyColumn; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; import javax.persistence.Table; import javax.persistence.Temporal; @@ -42,8 +44,21 @@ */ @Entity @Table(name = "device_code") +@NamedQueries({ + @NamedQuery(name = DeviceCode.QUERY_BY_USER_CODE, query = "select d from DeviceCode d where d.userCode = :" + DeviceCode.PARAM_USER_CODE), + @NamedQuery(name = DeviceCode.QUERY_BY_DEVICE_CODE, query = "select d from DeviceCode d where d.deviceCode = :" + DeviceCode.PARAM_DEVICE_CODE), + @NamedQuery(name = DeviceCode.QUERY_EXPIRED_BY_DATE, query = "select d from DeviceCode d where d.expiration <= :" + DeviceCode.PARAM_DATE) +}) public class DeviceCode { + public static final String QUERY_BY_USER_CODE = "DeviceCode.queryByUserCode"; + public static final String QUERY_BY_DEVICE_CODE = "DeviceCode.queryByDeviceCode"; + public static final String QUERY_EXPIRED_BY_DATE = "DeviceCode.queryExpiredByDate"; + + public static final String PARAM_USER_CODE = "userCode"; + public static final String PARAM_DEVICE_CODE = "deviceCode"; + public static final String PARAM_DATE = "date"; + private Long id; private String deviceCode; private String userCode; diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/impl/DeviceCodeRepository.java b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/impl/DeviceCodeRepository.java new file mode 100644 index 0000000000..955cf6773d --- /dev/null +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/impl/DeviceCodeRepository.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright 2017 The MITRE Corporation + * and the MIT Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +package org.mitre.oauth2.repository.impl; + +import java.util.Set; + +import org.mitre.oauth2.model.DeviceCode; + +/** + * @author jricher + * + */ +public interface DeviceCodeRepository { + + /** + * @param id + * @return + */ + public DeviceCode getById(Long id); + + /** + * @param deviceCode + * @return + */ + public DeviceCode getByDeviceCode(String deviceCode); + + /** + * @param scope + */ + public void remove(DeviceCode scope); + + /** + * @param scope + * @return + */ + public DeviceCode save(DeviceCode scope); + + /** + * @param userCode + * @return + */ + public DeviceCode getByUserCode(String userCode); + +} diff --git a/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql b/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql index 8f5e69ce7c..27d9c698db 100644 --- a/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql +++ b/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql @@ -131,7 +131,7 @@ CREATE TABLE IF NOT EXISTS client_details ( dynamically_registered BOOLEAN DEFAULT false NOT NULL, allow_introspection BOOLEAN DEFAULT false NOT NULL, id_token_validity_seconds BIGINT DEFAULT 600 NOT NULL, - device_code_validity_seconds BIGINT DEFAULT 600 NOT NULL, + device_code_validity_seconds BIGINT, client_id VARCHAR(256), client_secret VARCHAR(2048), diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaDeviceCodeRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaDeviceCodeRepository.java new file mode 100644 index 0000000000..a72555040b --- /dev/null +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaDeviceCodeRepository.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright 2017 The MITRE Corporation + * and the MIT Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ +/** + * + */ +package org.mitre.oauth2.repository.impl; + +import static org.mitre.util.jpa.JpaUtil.getSingleResult; +import static org.mitre.util.jpa.JpaUtil.saveOrUpdate; + +import java.util.LinkedHashSet; +import java.util.Set; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.TypedQuery; + +import org.mitre.oauth2.model.DeviceCode; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +/** + * @author jricher + * + */ +@Repository("jpaDeviceCodeRepository") +public class JpaDeviceCodeRepository implements DeviceCodeRepository { + + @PersistenceContext(unitName="defaultPersistenceUnit") + private EntityManager em; + + /* (non-Javadoc) + */ + @Override + @Transactional(value="defaultTransactionManager") + public DeviceCode getById(Long id) { + return em.find(DeviceCode.class, id); + } + + /* (non-Javadoc) + */ + @Override + @Transactional(value="defaultTransactionManager") + public DeviceCode getByUserCode(String value) { + TypedQuery query = em.createNamedQuery(DeviceCode.QUERY_BY_USER_CODE, DeviceCode.class); + query.setParameter(DeviceCode.PARAM_USER_CODE, value); + return getSingleResult(query.getResultList()); + } + + /* (non-Javadoc) + */ + @Override + @Transactional(value="defaultTransactionManager") + public DeviceCode getByDeviceCode(String value) { + TypedQuery query = em.createNamedQuery(DeviceCode.QUERY_BY_DEVICE_CODE, DeviceCode.class); + query.setParameter(DeviceCode.PARAM_DEVICE_CODE, value); + return getSingleResult(query.getResultList()); + } + + /* (non-Javadoc) + */ + @Override + @Transactional(value="defaultTransactionManager") + public void remove(DeviceCode scope) { + DeviceCode found = getById(scope.getId()); + + if (found != null) { + em.remove(found); + } + + } + + /* (non-Javadoc) + * @see org.mitre.oauth2.repository.SystemScopeRepository#save(org.mitre.oauth2.model.SystemScope) + */ + @Override + @Transactional(value="defaultTransactionManager") + public DeviceCode save(DeviceCode scope) { + return saveOrUpdate(scope.getId(), em, scope); + } + +} diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/InMemoryDeviceCodeService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java similarity index 75% rename from openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/InMemoryDeviceCodeService.java rename to openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java index eb522c5b69..0ef3677781 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/InMemoryDeviceCodeService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java @@ -18,15 +18,15 @@ package org.mitre.oauth2.service.impl; import java.util.Date; -import java.util.HashSet; import java.util.Map; import java.util.Set; import org.mitre.oauth2.model.AuthenticationHolderEntity; import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.model.DeviceCode; +import org.mitre.oauth2.repository.impl.DeviceCodeRepository; import org.mitre.oauth2.service.DeviceCodeService; -import org.springframework.security.core.Authentication; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.stereotype.Service; @@ -35,10 +35,11 @@ * @author jricher * */ -@Service -public class InMemoryDeviceCodeService implements DeviceCodeService { +@Service("defaultDeviceCodeService") +public class DefaultDeviceCodeService implements DeviceCodeService { - private Set codes = new HashSet<>(); + @Autowired + private DeviceCodeRepository repository; /* (non-Javadoc) * @see org.mitre.oauth2.service.DeviceCodeService#save(org.mitre.oauth2.model.DeviceCode) @@ -54,8 +55,7 @@ public DeviceCode createNewDeviceCode(String deviceCode, String userCode, Set response = new HashMap<>(); + response.put("device_code", deviceCode); + response.put("user_code", userCode); + response.put("verification_uri", config.getIssuer() + USER_URL); + if (client.getDeviceCodeValiditySeconds() != null) { + response.put("expires_in", client.getDeviceCodeValiditySeconds()); + } + + model.put(JsonEntityView.ENTITY, response); return JsonEntityView.VIEWNAME; From d83fbc6c67a5932b3c834593e9ef20717b9787f4 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Sat, 11 Mar 2017 17:57:06 -0500 Subject: [PATCH 345/465] UI for managing device code flow --- .../src/main/webapp/resources/js/client.js | 11 +++++++-- .../resources/js/locale/en/messages.json | 2 ++ .../webapp/resources/template/client.html | 24 ++++++++++++++++++- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/client.js b/openid-connect-server-webapp/src/main/webapp/resources/js/client.js index e59eaaba36..dcdd57bd14 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/client.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/client.js @@ -93,6 +93,7 @@ var ClientModel = Backbone.Model.extend({ dynamicallyRegistered:false, allowIntrospection:false, idTokenValiditySeconds: null, + deviceCodeValiditySeconds: null, createdAt:null, allowRefresh:false, @@ -790,7 +791,8 @@ var ClientFormView = Backbone.View.extend({ 'implicit': 'implicit', 'client_credentials': 'client_credentials', 'redelegate': 'urn:ietf:params:oauth:grant_type:redelegate', - 'refresh_token': 'refresh_token' + 'refresh_token': 'refresh_token', + 'device': 'urn:ietf:params:oauth:grant-type:device_code' }, // maps from a form-friendly name to the real response type parameter name @@ -863,7 +865,9 @@ var ClientFormView = Backbone.View.extend({ accessTokenValiditySeconds = this.getFormTokenNumberValue($('#accessTokenValidityTime input[type=text]').val(), $('#accessTokenValidityTime select').val()); } - var idTokenValiditySeconds = this.getFormTokenNumberValue($('#idTokenValidityTime input[type=text]').val(), $('#idTokenValidityTime select').val()); + var idTokenValiditySeconds = this.getFormTokenNumberValue($('#idTokenValidityTime input[type=text]').val(), $('#idTokenValidityTime select').val()); + + var deviceCodeValiditySeconds = this.getFormTokenNumberValue($('#deviceCodeValidityTime input[type=text]').val, $('#deviceCodeValidityTime select').val()); var refreshTokenValiditySeconds = null; if ($('#allowRefresh').is(':checked')) { @@ -928,6 +932,7 @@ var ClientFormView = Backbone.View.extend({ accessTokenValiditySeconds: accessTokenValiditySeconds, refreshTokenValiditySeconds: refreshTokenValiditySeconds, idTokenValiditySeconds: idTokenValiditySeconds, + deviceCodeValiditySeconds: deviceCodeValiditySeconds, allowRefresh: $('#allowRefresh').is(':checked'), allowIntrospection: $('#allowIntrospection input').is(':checked'), // <-- And here? --^ scope: scopes, @@ -1235,6 +1240,7 @@ ui.routes.push({path: "admin/client/new", name: "newClient", callback: accessTokenValiditySeconds:3600, refreshTokenValiditySeconds:24*3600, idTokenValiditySeconds:300, + deviceCodeValiditySeconds:30*60, grantTypes: ["authorization_code"], responseTypes: ["code"], subjectType: "PUBLIC", @@ -1252,6 +1258,7 @@ ui.routes.push({path: "admin/client/new", name: "newClient", callback: scope: _.uniq(_.flatten(app.systemScopeList.defaultScopes().pluck("value"))), accessTokenValiditySeconds:3600, idTokenValiditySeconds:600, + deviceCodeValiditySeconds:30*60, grantTypes: ["authorization_code"], responseTypes: ["code"], subjectType: "PUBLIC", diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json b/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json index 99329298ce..eb04ebbc1c 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json @@ -64,6 +64,8 @@ "rsa1-5": "RSAES-PKCS1-V1_5" }, "cryptography": "Crypto", + "device": "device", + "device-code-timeout": "Device Code Timeout", "display-secret": "Display/edit client secret:", "edit": "Edit Client", "generate-new-secret": "Generate a new client secret?", diff --git a/openid-connect-server-webapp/src/main/webapp/resources/template/client.html b/openid-connect-server-webapp/src/main/webapp/resources/template/client.html index 94d6775570..7a46786a69 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/template/client.html +++ b/openid-connect-server-webapp/src/main/webapp/resources/template/client.html @@ -359,7 +359,13 @@

<%-($.inArray("urn:ietf:params:oauth:grant_type:redelegate", client.grantTypes) > -1 ? 'checked' : '')%>> - + +
+ -1 ? 'checked' : '')%>> + +
+
@@ -611,6 +617,22 @@

Enter this time in seconds, minutes, or hours.

+ +
+ +
+
+ + +
+

Enter this time in seconds, minutes, or hours.

+
+
+
From 153776ecb5e09d05c6215d6ff5c3d6c93fe2f20f Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Sat, 11 Mar 2017 17:57:23 -0500 Subject: [PATCH 346/465] =?UTF-8?q?Don=E2=80=99t=20catch=20OAuth2=20errors?= =?UTF-8?q?,=20let=20the=20framework=20handle=20them=20here?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java index 2ba7a808b4..86f14c3b25 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java @@ -110,10 +110,6 @@ public String requestDeviceCode(@RequestParam("client_id") String clientId, @Req throw new InvalidClientException("Unauthorized grant type: " + DeviceTokenGranter.GRANT_TYPE); } - } catch (OAuth2Exception e) { - logger.error("OAuth2Exception was thrown when attempting to load client", e); - model.put(HttpCodeView.CODE, HttpStatus.BAD_REQUEST); - return HttpCodeView.VIEWNAME; } catch (IllegalArgumentException e) { logger.error("IllegalArgumentException was thrown when attempting to load client", e); model.put(HttpCodeView.CODE, HttpStatus.BAD_REQUEST); From cbf5bf742b493d9784fa4b78a62ecf935230a17d Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 13 Mar 2017 11:32:39 -0400 Subject: [PATCH 347/465] added messages for display pages, better error handling in user-facing pages --- .../webapp/WEB-INF/views/deviceApproved.jsp | 3 +- .../webapp/WEB-INF/views/requestUserCode.jsp | 43 +++++++++++-------- .../resources/js/locale/en/messages.json | 13 +++++- .../org/mitre/oauth2/web/DeviceEndpoint.java | 26 +++++------ 4 files changed, 52 insertions(+), 33 deletions(-) diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/deviceApproved.jsp b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/deviceApproved.jsp index a31898fe93..1b588f12ba 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/deviceApproved.jsp +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/deviceApproved.jsp @@ -23,10 +23,9 @@ - -
+
diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/requestUserCode.jsp b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/requestUserCode.jsp index ec80d9b5dd..51292fff4b 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/requestUserCode.jsp +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/requestUserCode.jsp @@ -15,29 +15,38 @@
-

  - - - - - - - - - -

+ +

 

+ + + + +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
- - - + + - -   - +
diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json b/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json index eb04ebbc1c..7eacdb1bc7 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json @@ -493,9 +493,20 @@ "device": { "request_code": { "title": "Enter Code", - "header": "Enter code for ", + "header": "Enter Code", "description": "Enter the code displayed on your device into the box below and press submit", "submit": "Submit" + }, + "error": { + "noUserCode": "The code that you entered was not found.", + "expiredUserCode": "The code that you entered has expired. Return to your device and request a new code.", + "userCodeAlreadyApproved": "The code that you entered has already been used.", + "userCodeMismatch": "There was an error processing the code you entered. Try refreshing the page and returning to your device to request a new code.", + "error": "There was an error processing the code you entered. Return to your device adn request a new code." + }, + "approve": { + "approved": "The device has been approved.", + "notApproved": "The device has not been approved." } } } \ No newline at end of file diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java index 86f14c3b25..fcf6e77783 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java @@ -178,20 +178,20 @@ public String readUserCode(@RequestParam("user_code") String userCode, ModelMap // we couldn't find the device code if (dc == null) { - // TODO: return error - return "error"; + model.addAttribute("error", "noUserCode"); + return "requestUserCode"; } // make sure the code hasn't expired yet if (dc.getExpiration() != null && dc.getExpiration().before(new Date())) { - // TODO: return an error - return "error"; + model.addAttribute("error", "expiredUserCode"); + return "requestUserCode"; } // make sure the device code hasn't already been approved if (dc.isApproved()) { - // TODO: return an error - return "error"; + model.addAttribute("error", "userCodeAlreadyApproved"); + return "requestUserCode"; } ClientDetailsEntity client = clientService.loadClientByClientId(dc.getClientId()); @@ -234,20 +234,20 @@ public String approveDevice(@RequestParam("user_code") String userCode, @Request // make sure the form that was submitted is the one that we were expecting if (!dc.getUserCode().equals(userCode)) { - // TODO: return an error - return "error"; + model.addAttribute("error", "userCodeMismatch"); + return "requestUserCode"; } // make sure the code hasn't expired yet if (dc.getExpiration() != null && dc.getExpiration().before(new Date())) { - // TODO: return an error - return "error"; + model.addAttribute("error", "expiredUserCode"); + return "requestUserCode"; } // user did not approve if (!approve) { - // TODO: return an error - return "error"; + model.addAttribute("approved", false); + return "deviceApproved"; } // create an OAuth request for storage @@ -277,7 +277,7 @@ public String approveDevice(@RequestParam("user_code") String userCode, @Request sortedScopes.addAll(Sets.difference(scopes, systemScopes)); model.put("scopes", sortedScopes); - + model.put("approved", true); return "deviceApproved"; } From f915196c2ea0d2ecf458d0316fb865f079c1e90b Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 13 Mar 2017 11:49:30 -0400 Subject: [PATCH 348/465] fix approval display --- .../src/main/webapp/WEB-INF/views/deviceApproved.jsp | 9 ++++++++- .../src/main/webapp/WEB-INF/views/requestUserCode.jsp | 8 ++++++-- .../main/java/org/mitre/oauth2/web/DeviceEndpoint.java | 8 ++++---- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/deviceApproved.jsp b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/deviceApproved.jsp index 1b588f12ba..80f601c633 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/deviceApproved.jsp +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/deviceApproved.jsp @@ -25,7 +25,14 @@ -
+ + +
+
+ +
+
+
diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/requestUserCode.jsp b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/requestUserCode.jsp index 51292fff4b..c629d0b9f0 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/requestUserCode.jsp +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/requestUserCode.jsp @@ -41,10 +41,14 @@ -
+
- +
+
+ +
+
diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java index fcf6e77783..a794ff73bf 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java @@ -244,6 +244,10 @@ public String approveDevice(@RequestParam("user_code") String userCode, @Request return "requestUserCode"; } + ClientDetailsEntity client = clientService.loadClientByClientId(dc.getClientId()); + + model.put("client", client); + // user did not approve if (!approve) { model.addAttribute("approved", false); @@ -256,10 +260,6 @@ public String approveDevice(@RequestParam("user_code") String userCode, @Request DeviceCode approvedCode = deviceCodeService.approveDeviceCode(dc, o2Auth); - ClientDetailsEntity client = clientService.loadClientByClientId(dc.getClientId()); - - model.put("client", client); - // pre-process the scopes Set scopes = scopeService.fromStrings(dc.getScope()); From f54d44cd9dd3c70fc380997677205b58a95c1810 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 14 Mar 2017 16:47:45 -0400 Subject: [PATCH 349/465] added device code to discovery, moved device endpoints --- .../java/org/mitre/discovery/web/DiscoveryEndpoint.java | 6 ++++-- .../src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java b/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java index 0949e17335..1c034924b4 100644 --- a/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java @@ -26,6 +26,7 @@ import org.mitre.jwt.signer.service.JWTSigningAndValidationService; import org.mitre.oauth2.model.PKCEAlgorithm; import org.mitre.oauth2.service.SystemScopeService; +import org.mitre.oauth2.web.DeviceEndpoint; import org.mitre.oauth2.web.IntrospectionEndpoint; import org.mitre.oauth2.web.RevocationEndpoint; import org.mitre.openid.connect.config.ConfigurationPropertiesBean; @@ -301,7 +302,7 @@ OPTIONAL. JSON array containing a list of the JWS signing algorithms (alg values JWSAlgorithm.ES256, JWSAlgorithm.ES384, JWSAlgorithm.ES512, JWSAlgorithm.PS256, JWSAlgorithm.PS384, JWSAlgorithm.PS512, Algorithm.NONE); - ArrayList grantTypes = Lists.newArrayList("authorization_code", "implicit", "urn:ietf:params:oauth:grant-type:jwt-bearer", "client_credentials", "urn:ietf:params:oauth:grant_type:redelegate"); + ArrayList grantTypes = Lists.newArrayList("authorization_code", "implicit", "urn:ietf:params:oauth:grant-type:jwt-bearer", "client_credentials", "urn:ietf:params:oauth:grant_type:redelegate", "urn:ietf:params:oauth:grant-type:device_code"); Map m = new HashMap<>(); m.put("issuer", config.getIssuer()); @@ -366,7 +367,8 @@ OPTIONAL. JSON array containing a list of the JWS signing algorithms (alg values m.put("revocation_endpoint", baseUrl + RevocationEndpoint.URL); // token revocation endpoint m.put("code_challenge_methods_supported", Lists.newArrayList(PKCEAlgorithm.plain.getName(), PKCEAlgorithm.S256.getName())); - + + m.put("device_authorization_endpoint", DeviceEndpoint.URL); model.addAttribute(JsonEntityView.ENTITY, m); diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java index a794ff73bf..a14f7dcb0b 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java @@ -73,8 +73,8 @@ @Controller public class DeviceEndpoint { - public static final String URL = "device"; - public static final String USER_URL = "device-user"; + public static final String URL = "devicecode"; + public static final String USER_URL = "device"; public static final Logger logger = LoggerFactory.getLogger(DeviceEndpoint.class); From f0c8b1b23554474185da7e1378b767c359442bf4 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 14 Mar 2017 17:38:46 -0400 Subject: [PATCH 350/465] fixed device code admin UI --- .../src/main/webapp/resources/js/client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/client.js b/openid-connect-server-webapp/src/main/webapp/resources/js/client.js index dcdd57bd14..cb963cd11a 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/client.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/client.js @@ -867,7 +867,7 @@ var ClientFormView = Backbone.View.extend({ var idTokenValiditySeconds = this.getFormTokenNumberValue($('#idTokenValidityTime input[type=text]').val(), $('#idTokenValidityTime select').val()); - var deviceCodeValiditySeconds = this.getFormTokenNumberValue($('#deviceCodeValidityTime input[type=text]').val, $('#deviceCodeValidityTime select').val()); + var deviceCodeValiditySeconds = this.getFormTokenNumberValue($('#deviceCodeValidityTime input[type=text]').val(), $('#deviceCodeValidityTime select').val()); var refreshTokenValiditySeconds = null; if ($('#allowRefresh').is(':checked')) { From 8406a89fd12a09929200beadf3ec5459c5b5057a Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 14 Mar 2017 17:39:57 -0400 Subject: [PATCH 351/465] added device flow expiration --- .../repository/impl/DeviceCodeRepository.java | 6 +++++ .../oauth2/service/DeviceCodeService.java | 4 +++- .../src/main/webapp/WEB-INF/task-config.xml | 1 + .../impl/JpaDeviceCodeRepository.java | 13 ++++++++++ .../impl/DefaultDeviceCodeService.java | 24 +++++++++++++++++++ 5 files changed, 47 insertions(+), 1 deletion(-) diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/impl/DeviceCodeRepository.java b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/impl/DeviceCodeRepository.java index 955cf6773d..011fd24c2a 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/impl/DeviceCodeRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/impl/DeviceCodeRepository.java @@ -17,6 +17,7 @@ package org.mitre.oauth2.repository.impl; +import java.util.Collection; import java.util.Set; import org.mitre.oauth2.model.DeviceCode; @@ -56,4 +57,9 @@ public interface DeviceCodeRepository { */ public DeviceCode getByUserCode(String userCode); + /** + * @return + */ + public Collection getExpiredCodes(); + } diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java b/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java index 6d5810e204..958dbc1d51 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java @@ -60,5 +60,7 @@ public interface DeviceCodeService { * @return */ public DeviceCode createNewDeviceCode(String deviceCode, String userCode, Set requestedScopes, ClientDetailsEntity client, Map parameters); - + + + public void clearExpiredDeviceCodes(); } diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/task-config.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/task-config.xml index 1b19c2152b..6f137dd48c 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/task-config.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/task-config.xml @@ -31,6 +31,7 @@ + diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaDeviceCodeRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaDeviceCodeRepository.java index a72555040b..91f34dfccf 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaDeviceCodeRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaDeviceCodeRepository.java @@ -22,6 +22,8 @@ import static org.mitre.util.jpa.JpaUtil.getSingleResult; import static org.mitre.util.jpa.JpaUtil.saveOrUpdate; +import java.util.Collection; +import java.util.Date; import java.util.LinkedHashSet; import java.util.Set; @@ -93,4 +95,15 @@ public DeviceCode save(DeviceCode scope) { return saveOrUpdate(scope.getId(), em, scope); } + /* (non-Javadoc) + * @see org.mitre.oauth2.repository.impl.DeviceCodeRepository#getExpiredCodes() + */ + @Override + @Transactional(value="defaultTransactionManager") + public Collection getExpiredCodes() { + TypedQuery query = em.createNamedQuery(DeviceCode.QUERY_EXPIRED_BY_DATE, DeviceCode.class); + query.setParameter(DeviceCode.PARAM_DATE, new Date()); + return query.getResultList(); + } + } diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java index 0ef3677781..ecd4c1684a 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java @@ -17,11 +17,14 @@ package org.mitre.oauth2.service.impl; +import java.util.Collection; import java.util.Date; import java.util.Map; import java.util.Set; +import org.mitre.data.AbstractPageOperationTemplate; import org.mitre.oauth2.model.AuthenticationHolderEntity; +import org.mitre.oauth2.model.AuthorizationCodeEntity; import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.model.DeviceCode; import org.mitre.oauth2.repository.impl.DeviceCodeRepository; @@ -30,6 +33,7 @@ import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; /** * @author jricher @@ -103,4 +107,24 @@ public DeviceCode consumeDeviceCode(String deviceCode, ClientDetails client) { } + /* (non-Javadoc) + * @see org.mitre.oauth2.service.DeviceCodeService#clearExpiredDeviceCodes() + */ + @Override + @Transactional(value="defaultTransactionManager") + public void clearExpiredDeviceCodes() { + + new AbstractPageOperationTemplate("clearExpiredDeviceCodes"){ + @Override + public Collection fetchPage() { + return repository.getExpiredCodes(); + } + + @Override + protected void doOperation(DeviceCode item) { + repository.remove(item); + } + }.execute(); + } + } From 22a4addfc029c756b560e19367088f1a6c51b7e8 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 15 Mar 2017 16:47:04 -0400 Subject: [PATCH 352/465] added software ID and software version --- .../oauth2/model/ClientDetailsEntity.java | 34 +++++++++++++++++++ .../mitre/oauth2/model/RegisteredClient.java | 32 +++++++++++++++++ .../oauth2/model/RegisteredClientFields.java | 3 +- .../ClientDetailsEntityJsonProcessor.java | 8 +++++ .../db/hsql/hsql_database_tables.sql | 2 ++ .../resources/js/locale/en/messages.json | 6 ++++ 6 files changed, 84 insertions(+), 1 deletion(-) diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/ClientDetailsEntity.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/ClientDetailsEntity.java index ed9e511ba1..2a4a0ea80f 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/ClientDetailsEntity.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/ClientDetailsEntity.java @@ -103,6 +103,8 @@ public class ClientDetailsEntity implements ClientDetails { private String policyUri; private String jwksUri; // URI pointer to keys private JWKSet jwks; // public key stored by value + private String softwareId; + private String softwareVersion; /** Fields from OIDC Client Registration Specification **/ private AppType applicationType; // application_type @@ -1049,4 +1051,36 @@ public void setDeviceCodeValiditySeconds(Integer deviceCodeValiditySeconds) { this.deviceCodeValiditySeconds = deviceCodeValiditySeconds; } + /** + * @return the softwareId + */ + @Basic + @Column(name="software_id") + public String getSoftwareId() { + return softwareId; + } + + /** + * @param softwareId the softwareId to set + */ + public void setSoftwareId(String softwareId) { + this.softwareId = softwareId; + } + + /** + * @return the softwareVersion + */ + @Basic + @Column(name="software_version") + public String getSoftwareVersion() { + return softwareVersion; + } + + /** + * @param softwareVersion the softwareVersion to set + */ + public void setSoftwareVersion(String softwareVersion) { + this.softwareVersion = softwareVersion; + } + } diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClient.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClient.java index f5e195899d..83baeb1548 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClient.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClient.java @@ -862,6 +862,38 @@ public void setDeviceCodeValiditySeconds(Integer deviceCodeValiditySeconds) { client.setDeviceCodeValiditySeconds(deviceCodeValiditySeconds); } + /** + * @return + * @see org.mitre.oauth2.model.ClientDetailsEntity#getSoftwareId() + */ + public String getSoftwareId() { + return client.getSoftwareId(); + } + + /** + * @param softwareId + * @see org.mitre.oauth2.model.ClientDetailsEntity#setSoftwareId(java.lang.String) + */ + public void setSoftwareId(String softwareId) { + client.setSoftwareId(softwareId); + } + + /** + * @return + * @see org.mitre.oauth2.model.ClientDetailsEntity#getSoftwareVersion() + */ + public String getSoftwareVersion() { + return client.getSoftwareVersion(); + } + + /** + * @param softwareVersion + * @see org.mitre.oauth2.model.ClientDetailsEntity#setSoftwareVersion(java.lang.String) + */ + public void setSoftwareVersion(String softwareVersion) { + client.setSoftwareVersion(softwareVersion); + } + } diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClientFields.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClientFields.java index 4f27707d2f..fe5f37e8cf 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClientFields.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClientFields.java @@ -17,6 +17,8 @@ package org.mitre.oauth2.model; public interface RegisteredClientFields { + public String SOFTWARE_ID = "software_id"; + public String SOFTWARE_VERSION = "software_version"; public String SOFTWARE_STATEMENT = "software_statement"; public String CLAIMS_REDIRECT_URIS = "claims_redirect_uris"; public String CLIENT_SECRET_EXPIRES_AT = "client_secret_expires_at"; @@ -57,5 +59,4 @@ public interface RegisteredClientFields { public String CLIENT_SECRET = "client_secret"; public String CLIENT_ID = "client_id"; public String CODE_CHALLENGE_METHOD = "code_challenge_method"; - } diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/ClientDetailsEntityJsonProcessor.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/ClientDetailsEntityJsonProcessor.java index feb3fce747..6957d685b0 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/ClientDetailsEntityJsonProcessor.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/ClientDetailsEntityJsonProcessor.java @@ -82,7 +82,9 @@ import static org.mitre.oauth2.model.RegisteredClientFields.SCOPE; import static org.mitre.oauth2.model.RegisteredClientFields.SCOPE_SEPARATOR; import static org.mitre.oauth2.model.RegisteredClientFields.SECTOR_IDENTIFIER_URI; +import static org.mitre.oauth2.model.RegisteredClientFields.SOFTWARE_ID; import static org.mitre.oauth2.model.RegisteredClientFields.SOFTWARE_STATEMENT; +import static org.mitre.oauth2.model.RegisteredClientFields.SOFTWARE_VERSION; import static org.mitre.oauth2.model.RegisteredClientFields.SUBJECT_TYPE; import static org.mitre.oauth2.model.RegisteredClientFields.TOKEN_ENDPOINT_AUTH_METHOD; import static org.mitre.oauth2.model.RegisteredClientFields.TOKEN_ENDPOINT_AUTH_SIGNING_ALG; @@ -206,6 +208,9 @@ public static ClientDetailsEntity parse(JsonElement jsonEl) { c.setCodeChallengeMethod(getAsPkceAlgorithm(o, CODE_CHALLENGE_METHOD)); + c.setSoftwareId(getAsString(o, SOFTWARE_ID)); + c.setSoftwareVersion(getAsString(o, SOFTWARE_VERSION)); + // note that this does not process or validate the software statement, that's handled in other components String softwareStatement = getAsString(o, SOFTWARE_STATEMENT); if (!Strings.isNullOrEmpty(softwareStatement)) { @@ -345,6 +350,9 @@ public static JsonObject serialize(RegisteredClient c) { o.addProperty(CODE_CHALLENGE_METHOD, c.getCodeChallengeMethod() != null ? c.getCodeChallengeMethod().getName() : null); + o.addProperty(SOFTWARE_ID, c.getSoftwareId()); + o.addProperty(SOFTWARE_VERSION, c.getSoftwareVersion()); + if (c.getSoftwareStatement() != null) { o.addProperty(SOFTWARE_STATEMENT, c.getSoftwareStatement().serialize()); } diff --git a/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql b/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql index 27d9c698db..00851a775e 100644 --- a/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql +++ b/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql @@ -171,6 +171,8 @@ CREATE TABLE IF NOT EXISTS client_details ( clear_access_tokens_on_refresh BOOLEAN DEFAULT true NOT NULL, software_statement VARCHAR(4096), + software_id VARCHAR(2048), + software_version VARCHAR(2048), code_challenge_method VARCHAR(256), diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json b/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json index 7eacdb1bc7..6cc12771dc 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json @@ -160,9 +160,15 @@ "ps384": "RSASSA-PSS using SHA-384 and MGF1 with SHA-384", "ps512": "RSASSA-PSS using SHA-512 and MGF1 with SHA-512" }, + "software-id": "Software ID", + "software-id-placeholder": "software ID...", + "software-id-help": "Identifier for the software in this client", "software-statement": "Software Statement", "software-statement-placeholder": "eyj0...", "software-statement-help": "A software statement is issued by a trusted third party and locks certain elements of a client's registration", + "software-version": "Software Version", + "software-version-placeholder": "1.0...", + "software-version-help": "Version of the software in this client", "subject-type": "Subject Type", "terms": "Terms of Service", "terms-help": "URL for the Terms of Service of this client, will be displayed to the user", From e57ea488b305e70d0b6d485a580ee815b52e2829 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 15 Mar 2017 17:30:26 -0400 Subject: [PATCH 353/465] fixed null handling on client admin pages, added software ID and version to UI --- .../src/main/webapp/resources/js/client.js | 55 ++++++++++------ .../src/main/webapp/resources/js/dynreg.js | 29 ++++++-- .../resources/js/locale/en/messages.json | 2 +- .../webapp/resources/template/client.html | 66 ++++++++++++------- .../webapp/resources/template/dynreg.html | 40 +++++++---- 5 files changed, 126 insertions(+), 66 deletions(-) diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/client.js b/openid-connect-server-webapp/src/main/webapp/resources/js/client.js index cb963cd11a..2ec5708d58 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/client.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/client.js @@ -34,26 +34,26 @@ var ClientModel = Backbone.Model.extend({ defaults:{ id:null, - clientId:"", - clientSecret:"", + clientId:null, + clientSecret:null, redirectUris:[], clientName:null, - clientUri:"", - logoUri:"", + clientUri:null, + logoUri:null, contacts:[], - tosUri:"", + tosUri:null, tokenEndpointAuthMethod:null, scope:[], grantTypes:[], responseTypes:[], - policyUri:"", + policyUri:null, - jwksUri:"", + jwksUri:null, jwks:null, jwksType:"URI", applicationType:null, - sectorIdentifierUri:"", + sectorIdentifierUri:null, subjectType:null, requestObjectSigningAlg:null, @@ -72,11 +72,15 @@ var ClientModel = Backbone.Model.extend({ requireAuthTime:false, defaultACRvalues:null, - initiateLoginUri:"", + initiateLoginUri:null, postLogoutRedirectUris:[], requestUris:[], + softwareStatement:null, + softwareId:null, + softwareVersion:null, + codeChallengeMethod:null, authorities:[], @@ -87,7 +91,7 @@ var ClientModel = Backbone.Model.extend({ claimsRedirectUris:[], - clientDescription:"", + clientDescription:null, reuseRefreshToken:true, clearAccessTokensOnRefresh:true, dynamicallyRegistered:false, @@ -769,6 +773,15 @@ var ClientFormView = Backbone.View.extend({ } }, + // returns "null" if the given value is falsy + emptyToNull:function(value) { + if (value) { + return value; + } else { + return null; + } + }, + disableUnsupportedJOSEItems:function(serverSupported, query) { var supported = ['default']; if (serverSupported) { @@ -921,33 +934,35 @@ var ClientFormView = Backbone.View.extend({ var attrs = { - clientName:$('#clientName input').val(), - clientId:$('#clientId input').val(), + clientName:this.emptyToNull($('#clientName input').val()), + clientId:this.emptyToNull($('#clientId input').val()), clientSecret: clientSecret, generateClientSecret:generateClientSecret, redirectUris: redirectUris, - clientDescription:$('#clientDescription textarea').val(), - logoUri:$('#logoUri input').val(), + clientDescription:this.emptyToNull($('#clientDescription textarea').val()), + logoUri:this.emptyToNull($('#logoUri input').val()), grantTypes: grantTypes, accessTokenValiditySeconds: accessTokenValiditySeconds, refreshTokenValiditySeconds: refreshTokenValiditySeconds, idTokenValiditySeconds: idTokenValiditySeconds, deviceCodeValiditySeconds: deviceCodeValiditySeconds, allowRefresh: $('#allowRefresh').is(':checked'), - allowIntrospection: $('#allowIntrospection input').is(':checked'), // <-- And here? --^ + allowIntrospection: $('#allowIntrospection input').is(':checked'), scope: scopes, - tosUri: $('#tosUri input').val(), - policyUri: $('#policyUri input').val(), - clientUri: $('#clientUri input').val(), + tosUri: this.emptyToNull($('#tosUri input').val()), + policyUri: this.emptyToNull($('#policyUri input').val()), + clientUri: this.emptyToNull($('#clientUri input').val()), applicationType: $('#applicationType input').filter(':checked').val(), jwksUri: jwksUri, jwks: jwks, subjectType: subjectType, - softwareStatement: $('#softwareStatement textarea').val(), + softwareStatement: this.emptyToNull($('#softwareStatement textarea').val()), + softwareId: this.emptyToNull($('#softwareId input').val()), + softwareVersion: this.emptyToNull($('#softwareVersion input').val()), tokenEndpointAuthMethod: tokenEndpointAuthMethod, responseTypes: responseTypes, sectorIdentifierUri: sectorIdentifierUri, - initiateLoginUri: $('#initiateLoginUri input').val(), + initiateLoginUri: this.emptyToNull($('#initiateLoginUri input').val()), postLogoutRedirectUris: this.postLogoutRedirectUrisCollection.pluck('item'), claimsRedirectUris: this.claimsRedirectUrisCollection.pluck('item'), reuseRefreshToken: $('#reuseRefreshToken').is(':checked'), diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/dynreg.js b/openid-connect-server-webapp/src/main/webapp/resources/js/dynreg.js index 9760ef535f..dca9fe2f25 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/dynreg.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/dynreg.js @@ -61,6 +61,10 @@ var DynRegClient = Backbone.Model.extend({ request_uris:[], + software_statement:null, + software_id:null, + software_version:null, + code_challenge_method:null, registration_access_token:null, @@ -313,6 +317,15 @@ var DynRegEditView = Backbone.View.extend({ } }, + // returns "null" if the given value is falsy + emptyToNull:function(value) { + if (value) { + return value; + } else { + return null; + } + }, + // maps from a form-friendly name to the real grant parameter name grantMap:{ 'authorization_code': 'authorization_code', @@ -405,24 +418,26 @@ var DynRegEditView = Backbone.View.extend({ } var attrs = { - client_name:$('#clientName input').val(), + client_name:this.emptyToNull($('#clientName input').val()), redirect_uris: redirectUris, - logo_uri:$('#logoUri input').val(), + logo_uri:this.emptyToNull($('#logoUri input').val()), grant_types: grantTypes, scope: scopes, client_secret: null, // never send a client secret - tos_uri: $('#tosUri input').val(), - policy_uri: $('#policyUri input').val(), - client_uri: $('#clientUri input').val(), + tos_uri: this.emptyToNull($('#tosUri input').val()), + policy_uri: this.emptyToNull($('#policyUri input').val()), + client_uri: this.emptyToNull($('#clientUri input').val()), application_type: $('#applicationType input').filter(':checked').val(), jwks_uri: jwksUri, jwks: jwks, subject_type: subjectType, - software_statement: $('#softwareStatement textarea').val(), + software_statement: this.emptyToNull($('#softwareStatement textarea').val()), + softwareId: this.emptyToNull($('#softwareId input').val()), + softwareVersion: this.emptyToNull($('#softwareVersion input').val()), token_endpoint_auth_method: $('#tokenEndpointAuthMethod input').filter(':checked').val(), response_types: responseTypes, sector_identifier_uri: sectorIdentifierUri, - initiate_login_uri: $('#initiateLoginUri input').val(), + initiate_login_uri: this.emptyToNull($('#initiateLoginUri input').val()), post_logout_redirect_uris: this.postLogoutRedirectUrisCollection.pluck('item'), claims_redirect_uris: this.claimsRedirectUrisCollection.pluck('item'), require_auth_time: $('#requireAuthTime input').is(':checked'), diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json b/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json index 6cc12771dc..1277794e4b 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json @@ -37,7 +37,7 @@ "client-description-placeholder": "Type a description", "client-id": "Client ID", "client-id-help": "Unique identifier. If you leave this blank it will be automatically generated.", - "client-id-placeholder": "Type something", + "client-id-placeholder": "Client ID will be automatically generated", "client-name": "Client name", "client-name-help": "Human-readable application name", "client-name-placeholder": "Type something", diff --git a/openid-connect-server-webapp/src/main/webapp/resources/template/client.html b/openid-connect-server-webapp/src/main/webapp/resources/template/client.html index 7a46786a69..b2de62da99 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/template/client.html +++ b/openid-connect-server-webapp/src/main/webapp/resources/template/client.html @@ -215,7 +215,7 @@

- +

Human-readable application name

@@ -223,7 +223,7 @@

- +

Unique identifier. If you leave this blank it will be automatically generated.

@@ -246,7 +246,7 @@

- +

URL that points to a logo image, will be displayed on approval page

@@ -260,7 +260,7 @@

- +

URL for the Terms of Service of this client, will be displayed to the user

@@ -268,7 +268,7 @@

- +

URL for the Policy Statement of this client, will be displayed to the user

@@ -276,23 +276,27 @@

- +

URL for the client's home page, will be displayed to the user

-
- -
-
- > - - > - -
-
-
- +
+ +
+ +

Identifier for the software in this client

+
+
+ +
+ +
+ +

Version of the software in this client

+
+
+
@@ -428,7 +432,7 @@

- +

Sector Identifier for JavaScript

@@ -490,7 +494,7 @@

- +
Generate on Save @@ -535,11 +539,11 @@

- +

URL for the client's JSON Web Key set (must be reachable by the server)

- +

Key set value (must be a valid JWK Set formatted key)

@@ -784,7 +788,7 @@

- +

URL to initiate login on the client

@@ -815,7 +819,7 @@

- +

Default maximum session age before re-prompting

@@ -832,7 +836,19 @@

-
+
+ +
+
+ > + + > + +
+
+
+ +
diff --git a/openid-connect-server-webapp/src/main/webapp/resources/template/dynreg.html b/openid-connect-server-webapp/src/main/webapp/resources/template/dynreg.html index ffed2638a8..11696ba72b 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/template/dynreg.html +++ b/openid-connect-server-webapp/src/main/webapp/resources/template/dynreg.html @@ -191,18 +191,22 @@

-
- -
- - -
-
- +
+ +
+ +

Identifier for the software in this client

+
+
+ +
+ +
+ +

Version of the software in this client

+
+
+
@@ -578,7 +582,17 @@

- +
+ +
+ + +
+
From 02928b048f54cc294a9e7aa7e6981ced6e963c34 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 15 Mar 2017 17:38:46 -0400 Subject: [PATCH 354/465] added software ID and version to data API --- .../connect/service/impl/MITREidDataService_1_3.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_3.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_3.java index be2fb65f1e..caa0110346 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_3.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_3.java @@ -149,6 +149,8 @@ public class MITREidDataService_1_3 extends MITREidDataServiceSupport implements private static final String ID = "id"; private static final String CODE_CHALLENGE_METHOD = "codeChallengeMethod"; private static final String SOFTWARE_STATEMENT = "softwareStatement"; + private static final String SOFTWARE_VERSION = "softwareVersion"; + private static final String SOFTWARE_ID = "softwareId"; /** * Logger for this class @@ -524,6 +526,8 @@ private void writeClients(JsonWriter writer) { writer.name(CLEAR_ACCESS_TOKENS_ON_REFRESH).value(client.isClearAccessTokensOnRefresh()); writer.name(DYNAMICALLY_REGISTERED).value(client.isDynamicallyRegistered()); writer.name(CODE_CHALLENGE_METHOD).value(client.getCodeChallengeMethod() != null ? client.getCodeChallengeMethod().getName() : null); + writer.name(SOFTWARE_ID).value(client.getSoftwareId()); + writer.name(SOFTWARE_VERSION).value(client.getSoftwareVersion()); writer.name(SOFTWARE_STATEMENT).value(client.getSoftwareStatement() != null ? client.getSoftwareStatement().serialize() : null); writer.endObject(); logger.debug("Wrote client {}", client.getId()); @@ -1155,6 +1159,10 @@ private void readClients(JsonReader reader) throws IOException { client.setDynamicallyRegistered(reader.nextBoolean()); } else if (name.equals(CODE_CHALLENGE_METHOD)) { client.setCodeChallengeMethod(PKCEAlgorithm.parse(reader.nextString())); + } else if (name.equals(SOFTWARE_ID)) { + client.setSoftwareId(reader.nextString()); + } else if (name.equals(SOFTWARE_VERSION)) { + client.setSoftwareVersion(reader.nextString()); } else if (name.equals(SOFTWARE_STATEMENT)) { try { client.setSoftwareStatement(JWTParser.parse(reader.nextString())); From 626b18d5cab885678e250f5c35dbade79d2326c4 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Thu, 16 Mar 2017 13:51:19 -0400 Subject: [PATCH 355/465] added software id and version to UI search --- .../src/main/webapp/resources/js/client.js | 6 ++++++ .../src/main/webapp/resources/js/locale/en/messages.json | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/client.js b/openid-connect-server-webapp/src/main/webapp/resources/js/client.js index 2ec5708d58..5e9f662022 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/client.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/client.js @@ -157,6 +157,12 @@ var ClientModel = Backbone.Model.extend({ matches.push($.t('client.client-table.match.scope')); } } + if (this.get('softwareId') != null && this.get('softwareId').toLowerCase().indexOf(term.toLowerCase()) != -1) { + matches.push($.t('client.client-table.match.software-id')); + } + if (this.get('softwareVersion') != null && this.get('softwareVersion').toLowerCase().indexOf(term.toLowerCase()) != -1) { + matches.push($.t('client.client-table.match.software-version')); + } } else { // there's no search term, we always match diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json b/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json index 1277794e4b..1989f3cac0 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/locale/en/messages.json @@ -202,7 +202,9 @@ "policy": "policy", "redirect": "redirect uri", "scope": "scope", - "terms": "terms of service" + "terms": "terms of service", + "software-id": "software ID", + "software-version": "version" }, "matched-search": "Matched search:", "new": "New Client", From 256b79ae5121afc56af5d45887733374f87b19a4 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Thu, 16 Mar 2017 17:20:04 -0400 Subject: [PATCH 356/465] lazy load client stats in UI --- .../openid/connect/model/ClientStat.java | 42 +++++++ .../openid/connect/service/StatsService.java | 8 +- .../src/main/webapp/resources/js/admin.js | 8 -- .../src/main/webapp/resources/js/client.js | 111 +++++++++++++++--- .../webapp/resources/template/client.html | 20 ++-- .../service/impl/DefaultStatsService.java | 33 +++--- .../mitre/openid/connect/web/StatsAPI.java | 25 ++-- 7 files changed, 182 insertions(+), 65 deletions(-) create mode 100644 openid-connect-common/src/main/java/org/mitre/openid/connect/model/ClientStat.java diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ClientStat.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ClientStat.java new file mode 100644 index 0000000000..585df3b2b5 --- /dev/null +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ClientStat.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright 2017 The MITRE Corporation + * and the MIT Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +package org.mitre.openid.connect.model; + +/** + * @author jricher + * + */ +public class ClientStat { + + private Integer approvedSiteCount; + + /** + * @return the count + */ + public Integer getApprovedSiteCount() { + return approvedSiteCount; + } + + /** + * @param count the count to set + */ + public void setApprovedSiteCount(Integer count) { + this.approvedSiteCount = count; + } + +} diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/StatsService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/StatsService.java index a1e45b716d..8b2be24bb3 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/StatsService.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/StatsService.java @@ -21,6 +21,8 @@ import java.util.Map; +import org.mitre.openid.connect.model.ClientStat; + /** * @author jricher * @@ -42,15 +44,15 @@ public interface StatsService { * * @return a map of id of client object to number of approvals */ - public Map getByClientId(); + public Map getByClientId(); /** * Calculate the usage count for a single client * - * @param id the id of the client to search on + * @param clientId the id of the client to search on * @return */ - public Integer getCountForClientId(Long id); + public ClientStat getCountForClientId(String clientId); /** * Trigger the stats to be recalculated upon next update. diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/admin.js b/openid-connect-server-webapp/src/main/webapp/resources/js/admin.js index a329c1caa4..fdbacdfbb0 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/admin.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/admin.js @@ -299,12 +299,6 @@ var BreadCrumbView = Backbone.View.extend({ }); -// Stats table - -var StatsModel = Backbone.Model.extend({ - url: "api/stats/byclientid" -}); - // User Profile var UserProfileView = Backbone.View.extend({ @@ -430,8 +424,6 @@ var AppRouter = Backbone.Router.extend({ initialize:function () { - this.clientStats = new StatsModel(); - this.breadCrumbView = new BreadCrumbView({ collection:new Backbone.Collection() }); diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/client.js b/openid-connect-server-webapp/src/main/webapp/resources/js/client.js index 5e9f662022..fceea87493 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/client.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/client.js @@ -194,6 +194,10 @@ var RegistrationTokenModel = Backbone.Model.extend({ urlRoot: 'api/tokens/registration' }); +var ClientStatsModel = Backbone.Model.extend({ + urlRoot: 'api/stats/byclientid' +}); + var ClientCollection = Backbone.Collection.extend({ initialize: function() { @@ -216,6 +220,8 @@ var ClientCollection = Backbone.Collection.extend({ var ClientView = Backbone.View.extend({ tagName: 'tr', + + isRendered: false, initialize:function (options) { this.options = options; @@ -236,6 +242,10 @@ var ClientView = Backbone.View.extend({ this.registrationTokenTemplate = _.template($('#tmpl-client-registration-token').html()); } + if (!this.countTemplate) { + this.countTemplate = _.template($('#tmpl-client-count').html()); + } + this.model.bind('change', this.render, this); }, @@ -259,7 +269,7 @@ var ClientView = Backbone.View.extend({ } - var json = {client: this.model.toJSON(), count: this.options.count, whiteList: this.options.whiteList, + var json = {client: this.model.toJSON(), whiteList: this.options.whiteList, displayCreationDate: displayCreationDate, hoverCreationDate: hoverCreationDate}; this.$el.html(this.template(json)); @@ -273,10 +283,19 @@ var ClientView = Backbone.View.extend({ this.$('.allow-introspection').tooltip({title: $.t('client.client-table.allow-introspection-tooltip')}); this.updateMatched(); + this.updateStats(); + $(this.el).i18n(); + + this.isRendered = true; + return this; }, + updateStats:function(eventName) { + $('.count', this.el).html(this.countTemplate({count: this.options.clientStat.get('approvedSiteCount')})); + }, + showRegistrationToken:function(e) { e.preventDefault(); @@ -412,6 +431,8 @@ var ClientListView = Backbone.View.extend({ tagName: 'span', + stats: {}, + initialize:function (options) { this.options = options; this.filteredModel = this.model; @@ -420,7 +441,6 @@ var ClientListView = Backbone.View.extend({ load:function(callback) { if (this.model.isFetched && this.options.whiteListList.isFetched && - this.options.stats.isFetched && this.options.systemScopeList.isFetched) { callback(); return; @@ -430,13 +450,11 @@ var ClientListView = Backbone.View.extend({ $('#loading').html( '' + $.t("common.clients") + ' ' + '' + $.t("whitelist.whitelist") + ' ' + - '' + $.t("common.scopes") + ' ' + - '' + $.t("common.statistics") + ' ' + '' + $.t("common.scopes") + ' ' ); $.when(this.model.fetchIfNeeded({success:function(e) {$('#loading-clients').addClass('label-success');}, error:app.errorHandlerView.handleError()}), this.options.whiteListList.fetchIfNeeded({success:function(e) {$('#loading-whitelist').addClass('label-success');}, error:app.errorHandlerView.handleError()}), - this.options.stats.fetchIfNeeded({success:function(e) {$('#loading-stats').addClass('label-success');}, error:app.errorHandlerView.handleError()}), this.options.systemScopeList.fetchIfNeeded({success:function(e) {$('#loading-scopes').addClass('label-success');}, error:app.errorHandlerView.handleError()})) .done(function() { $('#loadingbox').sheet('hide'); @@ -471,27 +489,44 @@ var ClientListView = Backbone.View.extend({ renderInner:function(eventName) { - // render the rows + // set up the rows to render + // (note that this doesn't render until visibility is determined in togglePlaceholder) + _.each(this.filteredModel.models, function (client, index) { + var clientStat = this.getStat(client.get('clientId')); var view = new ClientView({ - model:client, - count:this.options.stats.get(client.get('id')), + model:client, + clientStat:clientStat, systemScopeList: this.options.systemScopeList, whiteList: this.options.whiteListList.getByClientId(client.get('clientId')) }); view.parentView = this; - var element = view.render().el; + //var element = view.render().el; + var element = view.el; $("#client-table",this.el).append(element); - if (Math.ceil((index + 1) / 10) != 1) { - $(element).hide(); - } + this.addView(client.get('id'), view); }, this); this.togglePlaceholder(); - - }, + views:{}, + + addView:function(index, view) { + this.views[index] = view; + }, + + getView:function(index) { + return this.views[index]; + }, + + getStat:function(index) { + if (!this.stats[index]) { + this.stats[index] = new ClientStatsModel({id: index}); + } + return this.stats[index]; + }, + togglePlaceholder:function() { // set up pagination var numPages = Math.ceil(this.filteredModel.length / 10); @@ -508,6 +543,7 @@ var ClientListView = Backbone.View.extend({ } if (this.filteredModel.length > 0) { + this.changePage(undefined, 1); $('#client-table', this.el).show(); $('#client-table-empty', this.el).hide(); $('#client-table-search-empty', this.el).hide(); @@ -527,14 +563,54 @@ var ClientListView = Backbone.View.extend({ }, changePage:function(event, num) { + console.log('Page changed: ' + num); + $('.paginator', this.el).bootpag({page:num}); + var _self = this; + + _.each(this.filteredModel.models, function (client, index) { + var view = _self.getView(client.get('id')); + if (!view) { + console.log('Error: no view for client ' + client.get('id')); + return; + } + + // only show/render clients on the current page + + console.log(':: ' + index + ' ' + num + ' ' + Math.ceil((index + 1) / 10) != num); + + if (Math.ceil((index + 1) / 10) != num) { + $(view.el).hide(); + } else { + if (!view.isRendered) { + view.render(); + var clientStat = view.options.clientStat; + + // load and display the stats + $.when(clientStat.fetchIfNeeded({ + success:function(e) { + + }, + error:app.errorHandlerView.handleError()})) + .done(function(e) { + view.updateStats(); + }); + } + $(view.el).show(); + } + }); + + /* $('#client-table tbody tr', this.el).each(function(index, element) { if (Math.ceil((index + 1) / 10) != num) { + // hide the element $(element).hide(); } else { + // show the element $(element).show(); } }); + */ }, refreshTable:function(e) { @@ -543,14 +619,12 @@ var ClientListView = Backbone.View.extend({ $('#loading').html( '' + $.t("common.clients") + ' ' + '' + $.t("whitelist.whitelist") + ' ' + - '' + $.t("common.scopes") + ' ' + - '' + $.t("common.statistics") + ' ' + '' + $.t("common.scopes") + ' ' ); var _self = this; $.when(this.model.fetch({success:function(e) {$('#loading-clients').addClass('label-success');}, error:app.errorHandlerView.handleError()}), this.options.whiteListList.fetch({success:function(e) {$('#loading-whitelist').addClass('label-success');}, error:app.errorHandlerView.handleError()}), - this.options.stats.fetch({success:function(e) {$('#loading-stats').addClass('label-success');}, error:app.errorHandlerView.handleError()}), this.options.systemScopeList.fetch({success:function(e) {$('#loading-scopes').addClass('label-success');}, error:app.errorHandlerView.handleError()})) .done(function() { $('#loadingbox').sheet('hide'); @@ -1210,8 +1284,7 @@ ui.routes.push({path: "admin/clients", name: "listClients", callback: this.updateSidebar('admin/clients'); - var view = new ClientListView({model:this.clientList, stats: this.clientStats, systemScopeList: this.systemScopeList, whiteListList: this.whiteListList}); - + var view = new ClientListView({model:this.clientList, systemScopeList: this.systemScopeList, whiteListList: this.whiteListList}); view.load(function() { $('#content').html(view.render().el); view.delegateEvents(); diff --git a/openid-connect-server-webapp/src/main/webapp/resources/template/client.html b/openid-connect-server-webapp/src/main/webapp/resources/template/client.html index b2de62da99..0ee69eb580 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/template/client.html +++ b/openid-connect-server-webapp/src/main/webapp/resources/template/client.html @@ -17,14 +17,8 @@ + + \ No newline at end of file diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultStatsService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultStatsService.java index 26cc34571a..098596e3df 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultStatsService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultStatsService.java @@ -29,6 +29,7 @@ import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.service.ClientDetailsEntityService; import org.mitre.openid.connect.model.ApprovedSite; +import org.mitre.openid.connect.model.ClientStat; import org.mitre.openid.connect.service.ApprovedSiteService; import org.mitre.openid.connect.service.StatsService; import org.springframework.beans.factory.annotation.Autowired; @@ -65,12 +66,12 @@ public Map get() { }, 10, TimeUnit.MINUTES); } - private Supplier> byClientIdCache = createByClientIdCache(); + private Supplier> byClientIdCache = createByClientIdCache(); - private Supplier> createByClientIdCache() { - return Suppliers.memoizeWithExpiration(new Supplier>() { + private Supplier> createByClientIdCache() { + return Suppliers.memoizeWithExpiration(new Supplier>() { @Override - public Map get() { + public Map get() { return computeByClientId(); } @@ -107,11 +108,11 @@ private Map computeSummaryStats() { * @see org.mitre.openid.connect.service.StatsService#calculateByClientId() */ @Override - public Map getByClientId() { + public Map getByClientId() { return byClientIdCache.get(); } - private Map computeByClientId() { + private Map computeByClientId() { // get all approved sites Collection allSites = approvedSiteService.getAll(); @@ -120,10 +121,10 @@ private Map computeByClientId() { clientIds.add(approvedSite.getClientId()); } - Map counts = getEmptyClientCountMap(); + Map counts = getEmptyClientCountMap(); for (String clientId : clientIds) { ClientDetailsEntity client = clientService.loadClientByClientId(clientId); - counts.put(client.getId(), clientIds.count(clientId)); + counts.put(client.getClientId(), clientIds.count(clientId)); } return counts; @@ -133,22 +134,24 @@ private Map computeByClientId() { * @see org.mitre.openid.connect.service.StatsService#countForClientId(java.lang.String) */ @Override - public Integer getCountForClientId(Long id) { - - Map counts = getByClientId(); - return counts.get(id); + public ClientStat getCountForClientId(String id) { + Map counts = getByClientId(); + ClientStat stat = new ClientStat(); + stat.setApprovedSiteCount(counts.get(id)); + + return stat; } /** * Create a new map of all client ids set to zero * @return */ - private Map getEmptyClientCountMap() { - Map counts = new HashMap<>(); + private Map getEmptyClientCountMap() { + Map counts = new HashMap<>(); Collection clients = clientService.getAllClients(); for (ClientDetailsEntity client : clients) { - counts.put(client.getId(), 0); + counts.put(client.getClientId(), 0); } return counts; diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/StatsAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/StatsAPI.java index 2ac2ac51d4..7bbb44c711 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/StatsAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/StatsAPI.java @@ -18,6 +18,7 @@ import java.util.Map; +import org.mitre.openid.connect.model.ClientStat; import org.mitre.openid.connect.service.StatsService; import org.mitre.openid.connect.view.JsonEntityView; import org.slf4j.Logger; @@ -53,20 +54,20 @@ public String statsSummary(ModelMap m) { } - @PreAuthorize("hasRole('ROLE_USER')") - @RequestMapping(value = "byclientid", produces = MediaType.APPLICATION_JSON_VALUE) - public String statsByClient(ModelMap m) { - Map e = statsService.getByClientId(); - - m.put(JsonEntityView.ENTITY, e); - - return JsonEntityView.VIEWNAME; - } - +// @PreAuthorize("hasRole('ROLE_USER')") +// @RequestMapping(value = "byclientid", produces = MediaType.APPLICATION_JSON_VALUE) +// public String statsByClient(ModelMap m) { +// Map e = statsService.getByClientId(); +// +// m.put(JsonEntityView.ENTITY, e); +// +// return JsonEntityView.VIEWNAME; +// } +// @PreAuthorize("hasRole('ROLE_USER')") @RequestMapping(value = "byclientid/{id}", produces = MediaType.APPLICATION_JSON_VALUE) - public String statsByClientId(@PathVariable("id") Long id, ModelMap m) { - Integer e = statsService.getCountForClientId(id); + public String statsByClientId(@PathVariable("id") String clientId, ModelMap m) { + ClientStat e = statsService.getCountForClientId(clientId); m.put(JsonEntityView.ENTITY, e); From a926a8f0abf0b5de6528c8c893c2083e2fc1336f Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Thu, 16 Mar 2017 17:31:26 -0400 Subject: [PATCH 357/465] cleaned up server-side stats service, UI now uses per-client calls --- .../openid/connect/service/StatsService.java | 7 --- .../service/impl/DefaultStatsService.java | 63 ++----------------- 2 files changed, 4 insertions(+), 66 deletions(-) diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/StatsService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/StatsService.java index 8b2be24bb3..502094b603 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/StatsService.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/StatsService.java @@ -39,13 +39,6 @@ public interface StatsService { */ public Map getSummaryStats(); - /** - * Calculate usage count for all clients - * - * @return a map of id of client object to number of approvals - */ - public Map getByClientId(); - /** * Calculate the usage count for a single client * diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultStatsService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultStatsService.java index 098596e3df..c22c1dd58d 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultStatsService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultStatsService.java @@ -50,9 +50,6 @@ public class DefaultStatsService implements StatsService { @Autowired private ApprovedSiteService approvedSiteService; - @Autowired - private ClientDetailsEntityService clientService; - // stats cache private Supplier> summaryCache = createSummaryCache(); @@ -66,18 +63,6 @@ public Map get() { }, 10, TimeUnit.MINUTES); } - private Supplier> byClientIdCache = createByClientIdCache(); - - private Supplier> createByClientIdCache() { - return Suppliers.memoizeWithExpiration(new Supplier>() { - @Override - public Map get() { - return computeByClientId(); - } - - }, 10, TimeUnit.MINUTES); - } - @Override public Map getSummaryStats() { return summaryCache.get(); @@ -104,66 +89,26 @@ private Map computeSummaryStats() { return e; } - /* (non-Javadoc) - * @see org.mitre.openid.connect.service.StatsService#calculateByClientId() - */ - @Override - public Map getByClientId() { - return byClientIdCache.get(); - } - - private Map computeByClientId() { - // get all approved sites - Collection allSites = approvedSiteService.getAll(); - - Multiset clientIds = HashMultiset.create(); - for (ApprovedSite approvedSite : allSites) { - clientIds.add(approvedSite.getClientId()); - } - - Map counts = getEmptyClientCountMap(); - for (String clientId : clientIds) { - ClientDetailsEntity client = clientService.loadClientByClientId(clientId); - counts.put(client.getClientId(), clientIds.count(clientId)); - } - - return counts; - } - /* (non-Javadoc) * @see org.mitre.openid.connect.service.StatsService#countForClientId(java.lang.String) */ @Override - public ClientStat getCountForClientId(String id) { + public ClientStat getCountForClientId(String clientId) { - Map counts = getByClientId(); + Collection approvedSites = approvedSiteService.getByClientId(clientId); + ClientStat stat = new ClientStat(); - stat.setApprovedSiteCount(counts.get(id)); + stat.setApprovedSiteCount(approvedSites.size()); return stat; } - /** - * Create a new map of all client ids set to zero - * @return - */ - private Map getEmptyClientCountMap() { - Map counts = new HashMap<>(); - Collection clients = clientService.getAllClients(); - for (ClientDetailsEntity client : clients) { - counts.put(client.getClientId(), 0); - } - - return counts; - } - /** * Reset both stats caches on a trigger (before the timer runs out). Resets the timers. */ @Override public void resetCache() { summaryCache = createSummaryCache(); - byClientIdCache = createByClientIdCache(); } } From 2a75535dce1f94240a333aea13d15e51fc607315 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Thu, 16 Mar 2017 17:55:31 -0400 Subject: [PATCH 358/465] fix unit tests and downstream calls --- .../web/OAuthConfirmationController.java | 2 +- .../service/impl/TestDefaultStatsService.java | 48 ++++--------------- 2 files changed, 11 insertions(+), 39 deletions(-) diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java index 4e0ca9c142..39d356c85d 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java @@ -201,7 +201,7 @@ public String confimAccess(Map model, @ModelAttribute("authoriza model.put("claims", claimsForScopes); // client stats - Integer count = statsService.getCountForClientId(client.getId()); + Integer count = statsService.getCountForClientId(client.getClientId()).getApprovedSiteCount(); model.put("count", count); diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultStatsService.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultStatsService.java index fb8ae78f99..930e659558 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultStatsService.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultStatsService.java @@ -71,9 +71,6 @@ public class TestDefaultStatsService { @Mock private ApprovedSiteService approvedSiteService; - @Mock - private ClientDetailsEntityService clientService; - @InjectMocks private DefaultStatsService service = new DefaultStatsService(); @@ -84,7 +81,7 @@ public class TestDefaultStatsService { @Before public void prepare() { - Mockito.reset(approvedSiteService, clientService); + Mockito.reset(approvedSiteService); Mockito.when(ap1.getUserId()).thenReturn(userId1); Mockito.when(ap1.getClientId()).thenReturn(clientId1); @@ -111,11 +108,10 @@ public void prepare() { Mockito.when(client3.getId()).thenReturn(3L); Mockito.when(client4.getId()).thenReturn(4L); - Mockito.when(clientService.getAllClients()).thenReturn(Sets.newHashSet(client1, client2, client3, client4)); - Mockito.when(clientService.loadClientByClientId(clientId1)).thenReturn(client1); - Mockito.when(clientService.loadClientByClientId(clientId2)).thenReturn(client2); - Mockito.when(clientService.loadClientByClientId(clientId3)).thenReturn(client3); - Mockito.when(clientService.loadClientByClientId(clientId4)).thenReturn(client4); + Mockito.when(approvedSiteService.getByClientId(clientId1)).thenReturn(Sets.newHashSet(ap1, ap2)); + Mockito.when(approvedSiteService.getByClientId(clientId2)).thenReturn(Sets.newHashSet(ap3)); + Mockito.when(approvedSiteService.getByClientId(clientId3)).thenReturn(Sets.newHashSet(ap4)); + Mockito.when(approvedSiteService.getByClientId(clientId4)).thenReturn(Sets.newHashSet()); } @Test @@ -139,37 +135,13 @@ public void calculateSummaryStats() { assertThat(stats.get("clientCount"), is(3)); } - @Test - public void calculateByClientId_empty() { - - Mockito.when(approvedSiteService.getAll()).thenReturn(new HashSet()); - - Map stats = service.getByClientId(); - - assertThat(stats.get(1L), is(0)); - assertThat(stats.get(2L), is(0)); - assertThat(stats.get(3L), is(0)); - assertThat(stats.get(4L), is(0)); - } - - @Test - public void calculateByClientId() { - - Map stats = service.getByClientId(); - - assertThat(stats.get(1L), is(2)); - assertThat(stats.get(2L), is(1)); - assertThat(stats.get(3L), is(1)); - assertThat(stats.get(4L), is(0)); - } - @Test public void countForClientId() { - - assertThat(service.getCountForClientId(1L), is(2)); - assertThat(service.getCountForClientId(2L), is(1)); - assertThat(service.getCountForClientId(3L), is(1)); - assertThat(service.getCountForClientId(4L), is(0)); + // stats for ap1..ap4 + assertThat(service.getCountForClientId(clientId1).getApprovedSiteCount(), is(2)); + assertThat(service.getCountForClientId(clientId2).getApprovedSiteCount(), is(1)); + assertThat(service.getCountForClientId(clientId3).getApprovedSiteCount(), is(1)); + assertThat(service.getCountForClientId(clientId4).getApprovedSiteCount(), is(0)); } @Test From c377e411e390ad13ea4fd081d538751a583b808b Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 17 Mar 2017 16:32:41 -0400 Subject: [PATCH 359/465] removed packed-in bootstrap files (again) --- .../bootstrap2/css/bootstrap-responsive.css | 1089 ---- .../resources/bootstrap2/css/bootstrap.css | 5236 ----------------- 2 files changed, 6325 deletions(-) delete mode 100644 openid-connect-server-webapp/src/main/webapp/resources/bootstrap2/css/bootstrap-responsive.css delete mode 100644 openid-connect-server-webapp/src/main/webapp/resources/bootstrap2/css/bootstrap.css diff --git a/openid-connect-server-webapp/src/main/webapp/resources/bootstrap2/css/bootstrap-responsive.css b/openid-connect-server-webapp/src/main/webapp/resources/bootstrap2/css/bootstrap-responsive.css deleted file mode 100644 index ac63813ee1..0000000000 --- a/openid-connect-server-webapp/src/main/webapp/resources/bootstrap2/css/bootstrap-responsive.css +++ /dev/null @@ -1,1089 +0,0 @@ -/*! - * Bootstrap Responsive v2.3.2 - * - * Copyright 2013 Twitter, Inc - * Licensed under the Apache License v2.0 - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Designed and built with all the love in the world by @mdo and @fat. - */ -.clearfix { - *zoom: 1; -} -.clearfix:before, -.clearfix:after { - display: table; - content: ""; - line-height: 0; -} -.clearfix:after { - clear: both; -} -.hide-text { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0; -} -.input-block-level { - display: block; - width: 100%; - min-height: 30px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -@-ms-viewport { - width: device-width; -} -.hidden { - display: none; - visibility: hidden; -} -.visible-phone { - display: none !important; -} -.visible-tablet { - display: none !important; -} -.hidden-desktop { - display: none !important; -} -.visible-desktop { - display: inherit !important; -} -@media (min-width: 768px) and (max-width: 979px) { - .hidden-desktop { - display: inherit !important; - } - .visible-desktop { - display: none !important ; - } - .visible-tablet { - display: inherit !important; - } - .hidden-tablet { - display: none !important; - } -} -@media (max-width: 767px) { - .hidden-desktop { - display: inherit !important; - } - .visible-desktop { - display: none !important; - } - .visible-phone { - display: inherit !important; - } - .hidden-phone { - display: none !important; - } -} -.visible-print { - display: none !important; -} -@media print { - .visible-print { - display: inherit !important; - } - .hidden-print { - display: none !important; - } -} -@media (min-width: 1200px) { - .row { - margin-left: -30px; - *zoom: 1; - } - .row:before, - .row:after { - display: table; - content: ""; - line-height: 0; - } - .row:after { - clear: both; - } - [class*="span"] { - float: left; - min-height: 1px; - margin-left: 30px; - } - .container, - .navbar-static-top .container, - .navbar-fixed-top .container, - .navbar-fixed-bottom .container { - width: 1170px; - } - .span12 { - width: 1170px; - } - .span11 { - width: 1070px; - } - .span10 { - width: 970px; - } - .span9 { - width: 870px; - } - .span8 { - width: 770px; - } - .span7 { - width: 670px; - } - .span6 { - width: 570px; - } - .span5 { - width: 470px; - } - .span4 { - width: 370px; - } - .span3 { - width: 270px; - } - .span2 { - width: 170px; - } - .span1 { - width: 70px; - } - .offset12 { - margin-left: 1230px; - } - .offset11 { - margin-left: 1130px; - } - .offset10 { - margin-left: 1030px; - } - .offset9 { - margin-left: 930px; - } - .offset8 { - margin-left: 830px; - } - .offset7 { - margin-left: 730px; - } - .offset6 { - margin-left: 630px; - } - .offset5 { - margin-left: 530px; - } - .offset4 { - margin-left: 430px; - } - .offset3 { - margin-left: 330px; - } - .offset2 { - margin-left: 230px; - } - .offset1 { - margin-left: 130px; - } - .row-fluid { - width: 100%; - *zoom: 1; - } - .row-fluid:before, - .row-fluid:after { - display: table; - content: ""; - line-height: 0; - } - .row-fluid:after { - clear: both; - } - .row-fluid [class*="span"] { - display: block; - width: 100%; - min-height: 30px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - float: left; - margin-left: 2.56410256%; - *margin-left: 2.51091107%; - } - .row-fluid [class*="span"]:first-child { - margin-left: 0; - } - .row-fluid .controls-row [class*="span"] + [class*="span"] { - margin-left: 2.56410256%; - } - .row-fluid .span12 { - width: 100%; - *width: 99.94680851%; - } - .row-fluid .span11 { - width: 91.45299145%; - *width: 91.39979996%; - } - .row-fluid .span10 { - width: 82.90598291%; - *width: 82.85279142%; - } - .row-fluid .span9 { - width: 74.35897436%; - *width: 74.30578287%; - } - .row-fluid .span8 { - width: 65.81196581%; - *width: 65.75877432%; - } - .row-fluid .span7 { - width: 57.26495726%; - *width: 57.21176578%; - } - .row-fluid .span6 { - width: 48.71794872%; - *width: 48.66475723%; - } - .row-fluid .span5 { - width: 40.17094017%; - *width: 40.11774868%; - } - .row-fluid .span4 { - width: 31.62393162%; - *width: 31.57074013%; - } - .row-fluid .span3 { - width: 23.07692308%; - *width: 23.02373159%; - } - .row-fluid .span2 { - width: 14.52991453%; - *width: 14.47672304%; - } - .row-fluid .span1 { - width: 5.98290598%; - *width: 5.92971449%; - } - .row-fluid .offset12 { - margin-left: 105.12820513%; - *margin-left: 105.02182215%; - } - .row-fluid .offset12:first-child { - margin-left: 102.56410256%; - *margin-left: 102.45771959%; - } - .row-fluid .offset11 { - margin-left: 96.58119658%; - *margin-left: 96.4748136%; - } - .row-fluid .offset11:first-child { - margin-left: 94.01709402%; - *margin-left: 93.91071104%; - } - .row-fluid .offset10 { - margin-left: 88.03418803%; - *margin-left: 87.92780506%; - } - .row-fluid .offset10:first-child { - margin-left: 85.47008547%; - *margin-left: 85.36370249%; - } - .row-fluid .offset9 { - margin-left: 79.48717949%; - *margin-left: 79.38079651%; - } - .row-fluid .offset9:first-child { - margin-left: 76.92307692%; - *margin-left: 76.81669394%; - } - .row-fluid .offset8 { - margin-left: 70.94017094%; - *margin-left: 70.83378796%; - } - .row-fluid .offset8:first-child { - margin-left: 68.37606838%; - *margin-left: 68.2696854%; - } - .row-fluid .offset7 { - margin-left: 62.39316239%; - *margin-left: 62.28677941%; - } - .row-fluid .offset7:first-child { - margin-left: 59.82905983%; - *margin-left: 59.72267685%; - } - .row-fluid .offset6 { - margin-left: 53.84615385%; - *margin-left: 53.73977087%; - } - .row-fluid .offset6:first-child { - margin-left: 51.28205128%; - *margin-left: 51.1756683%; - } - .row-fluid .offset5 { - margin-left: 45.2991453%; - *margin-left: 45.19276232%; - } - .row-fluid .offset5:first-child { - margin-left: 42.73504274%; - *margin-left: 42.62865976%; - } - .row-fluid .offset4 { - margin-left: 36.75213675%; - *margin-left: 36.64575377%; - } - .row-fluid .offset4:first-child { - margin-left: 34.18803419%; - *margin-left: 34.08165121%; - } - .row-fluid .offset3 { - margin-left: 28.20512821%; - *margin-left: 28.09874523%; - } - .row-fluid .offset3:first-child { - margin-left: 25.64102564%; - *margin-left: 25.53464266%; - } - .row-fluid .offset2 { - margin-left: 19.65811966%; - *margin-left: 19.55173668%; - } - .row-fluid .offset2:first-child { - margin-left: 17.09401709%; - *margin-left: 16.98763412%; - } - .row-fluid .offset1 { - margin-left: 11.11111111%; - *margin-left: 11.00472813%; - } - .row-fluid .offset1:first-child { - margin-left: 8.54700855%; - *margin-left: 8.44062557%; - } - input, - textarea, - .uneditable-input { - margin-left: 0; - } - .controls-row [class*="span"] + [class*="span"] { - margin-left: 30px; - } - input.span12, - textarea.span12, - .uneditable-input.span12 { - width: 1156px; - } - input.span11, - textarea.span11, - .uneditable-input.span11 { - width: 1056px; - } - input.span10, - textarea.span10, - .uneditable-input.span10 { - width: 956px; - } - input.span9, - textarea.span9, - .uneditable-input.span9 { - width: 856px; - } - input.span8, - textarea.span8, - .uneditable-input.span8 { - width: 756px; - } - input.span7, - textarea.span7, - .uneditable-input.span7 { - width: 656px; - } - input.span6, - textarea.span6, - .uneditable-input.span6 { - width: 556px; - } - input.span5, - textarea.span5, - .uneditable-input.span5 { - width: 456px; - } - input.span4, - textarea.span4, - .uneditable-input.span4 { - width: 356px; - } - input.span3, - textarea.span3, - .uneditable-input.span3 { - width: 256px; - } - input.span2, - textarea.span2, - .uneditable-input.span2 { - width: 156px; - } - input.span1, - textarea.span1, - .uneditable-input.span1 { - width: 56px; - } - .thumbnails { - margin-left: -30px; - } - .thumbnails > li { - margin-left: 30px; - } - .row-fluid .thumbnails { - margin-left: 0; - } -} -@media (min-width: 768px) and (max-width: 979px) { - .row { - margin-left: -20px; - *zoom: 1; - } - .row:before, - .row:after { - display: table; - content: ""; - line-height: 0; - } - .row:after { - clear: both; - } - [class*="span"] { - float: left; - min-height: 1px; - margin-left: 20px; - } - .container, - .navbar-static-top .container, - .navbar-fixed-top .container, - .navbar-fixed-bottom .container { - width: 724px; - } - .span12 { - width: 724px; - } - .span11 { - width: 662px; - } - .span10 { - width: 600px; - } - .span9 { - width: 538px; - } - .span8 { - width: 476px; - } - .span7 { - width: 414px; - } - .span6 { - width: 352px; - } - .span5 { - width: 290px; - } - .span4 { - width: 228px; - } - .span3 { - width: 166px; - } - .span2 { - width: 104px; - } - .span1 { - width: 42px; - } - .offset12 { - margin-left: 764px; - } - .offset11 { - margin-left: 702px; - } - .offset10 { - margin-left: 640px; - } - .offset9 { - margin-left: 578px; - } - .offset8 { - margin-left: 516px; - } - .offset7 { - margin-left: 454px; - } - .offset6 { - margin-left: 392px; - } - .offset5 { - margin-left: 330px; - } - .offset4 { - margin-left: 268px; - } - .offset3 { - margin-left: 206px; - } - .offset2 { - margin-left: 144px; - } - .offset1 { - margin-left: 82px; - } - .row-fluid { - width: 100%; - *zoom: 1; - } - .row-fluid:before, - .row-fluid:after { - display: table; - content: ""; - line-height: 0; - } - .row-fluid:after { - clear: both; - } - .row-fluid [class*="span"] { - display: block; - width: 100%; - min-height: 30px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - float: left; - margin-left: 2.76243094%; - *margin-left: 2.70923945%; - } - .row-fluid [class*="span"]:first-child { - margin-left: 0; - } - .row-fluid .controls-row [class*="span"] + [class*="span"] { - margin-left: 2.76243094%; - } - .row-fluid .span12 { - width: 100%; - *width: 99.94680851%; - } - .row-fluid .span11 { - width: 91.43646409%; - *width: 91.3832726%; - } - .row-fluid .span10 { - width: 82.87292818%; - *width: 82.81973669%; - } - .row-fluid .span9 { - width: 74.30939227%; - *width: 74.25620078%; - } - .row-fluid .span8 { - width: 65.74585635%; - *width: 65.69266486%; - } - .row-fluid .span7 { - width: 57.18232044%; - *width: 57.12912895%; - } - .row-fluid .span6 { - width: 48.61878453%; - *width: 48.56559304%; - } - .row-fluid .span5 { - width: 40.05524862%; - *width: 40.00205713%; - } - .row-fluid .span4 { - width: 31.49171271%; - *width: 31.43852122%; - } - .row-fluid .span3 { - width: 22.9281768%; - *width: 22.87498531%; - } - .row-fluid .span2 { - width: 14.36464088%; - *width: 14.31144939%; - } - .row-fluid .span1 { - width: 5.80110497%; - *width: 5.74791348%; - } - .row-fluid .offset12 { - margin-left: 105.52486188%; - *margin-left: 105.4184789%; - } - .row-fluid .offset12:first-child { - margin-left: 102.76243094%; - *margin-left: 102.65604796%; - } - .row-fluid .offset11 { - margin-left: 96.96132597%; - *margin-left: 96.85494299%; - } - .row-fluid .offset11:first-child { - margin-left: 94.19889503%; - *margin-left: 94.09251205%; - } - .row-fluid .offset10 { - margin-left: 88.39779006%; - *margin-left: 88.29140708%; - } - .row-fluid .offset10:first-child { - margin-left: 85.63535912%; - *margin-left: 85.52897614%; - } - .row-fluid .offset9 { - margin-left: 79.83425414%; - *margin-left: 79.72787116%; - } - .row-fluid .offset9:first-child { - margin-left: 77.0718232%; - *margin-left: 76.96544023%; - } - .row-fluid .offset8 { - margin-left: 71.27071823%; - *margin-left: 71.16433525%; - } - .row-fluid .offset8:first-child { - margin-left: 68.50828729%; - *margin-left: 68.40190431%; - } - .row-fluid .offset7 { - margin-left: 62.70718232%; - *margin-left: 62.60079934%; - } - .row-fluid .offset7:first-child { - margin-left: 59.94475138%; - *margin-left: 59.8383684%; - } - .row-fluid .offset6 { - margin-left: 54.14364641%; - *margin-left: 54.03726343%; - } - .row-fluid .offset6:first-child { - margin-left: 51.38121547%; - *margin-left: 51.27483249%; - } - .row-fluid .offset5 { - margin-left: 45.5801105%; - *margin-left: 45.47372752%; - } - .row-fluid .offset5:first-child { - margin-left: 42.81767956%; - *margin-left: 42.71129658%; - } - .row-fluid .offset4 { - margin-left: 37.01657459%; - *margin-left: 36.91019161%; - } - .row-fluid .offset4:first-child { - margin-left: 34.25414365%; - *margin-left: 34.14776067%; - } - .row-fluid .offset3 { - margin-left: 28.45303867%; - *margin-left: 28.3466557%; - } - .row-fluid .offset3:first-child { - margin-left: 25.69060773%; - *margin-left: 25.58422476%; - } - .row-fluid .offset2 { - margin-left: 19.88950276%; - *margin-left: 19.78311978%; - } - .row-fluid .offset2:first-child { - margin-left: 17.12707182%; - *margin-left: 17.02068884%; - } - .row-fluid .offset1 { - margin-left: 11.32596685%; - *margin-left: 11.21958387%; - } - .row-fluid .offset1:first-child { - margin-left: 8.56353591%; - *margin-left: 8.45715293%; - } - input, - textarea, - .uneditable-input { - margin-left: 0; - } - .controls-row [class*="span"] + [class*="span"] { - margin-left: 20px; - } - input.span12, - textarea.span12, - .uneditable-input.span12 { - width: 710px; - } - input.span11, - textarea.span11, - .uneditable-input.span11 { - width: 648px; - } - input.span10, - textarea.span10, - .uneditable-input.span10 { - width: 586px; - } - input.span9, - textarea.span9, - .uneditable-input.span9 { - width: 524px; - } - input.span8, - textarea.span8, - .uneditable-input.span8 { - width: 462px; - } - input.span7, - textarea.span7, - .uneditable-input.span7 { - width: 400px; - } - input.span6, - textarea.span6, - .uneditable-input.span6 { - width: 338px; - } - input.span5, - textarea.span5, - .uneditable-input.span5 { - width: 276px; - } - input.span4, - textarea.span4, - .uneditable-input.span4 { - width: 214px; - } - input.span3, - textarea.span3, - .uneditable-input.span3 { - width: 152px; - } - input.span2, - textarea.span2, - .uneditable-input.span2 { - width: 90px; - } - input.span1, - textarea.span1, - .uneditable-input.span1 { - width: 28px; - } -} -@media (max-width: 767px) { - body { - padding-left: 20px; - padding-right: 20px; - } - .navbar-fixed-top, - .navbar-fixed-bottom, - .navbar-static-top { - margin-left: -20px; - margin-right: -20px; - } - .container-fluid { - padding: 0; - } - .dl-horizontal dt { - float: none; - clear: none; - width: auto; - text-align: left; - } - .dl-horizontal dd { - margin-left: 0; - } - .container { - width: auto; - } - .row-fluid { - width: 100%; - } - .row, - .thumbnails { - margin-left: 0; - } - .thumbnails > li { - float: none; - margin-left: 0; - } - [class*="span"], - .uneditable-input[class*="span"], - .row-fluid [class*="span"] { - float: none; - display: block; - width: 100%; - margin-left: 0; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - } - .span12, - .row-fluid .span12 { - width: 100%; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - } - .row-fluid [class*="offset"]:first-child { - margin-left: 0; - } - .input-large, - .input-xlarge, - .input-xxlarge, - input[class*="span"], - select[class*="span"], - textarea[class*="span"], - .uneditable-input { - display: block; - width: 100%; - min-height: 30px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - } - .input-prepend input, - .input-append input, - .input-prepend input[class*="span"], - .input-append input[class*="span"] { - display: inline-block; - width: auto; - } - .controls-row [class*="span"] + [class*="span"] { - margin-left: 0; - } - .modal { - position: fixed; - top: 20px; - left: 20px; - right: 20px; - width: auto; - margin: 0; - } - .modal.fade { - top: -100px; - } - .modal.fade.in { - top: 20px; - } -} -@media (max-width: 480px) { - .nav-collapse { - -webkit-transform: translate3d(0, 0, 0); - } - .page-header h1 small { - display: block; - line-height: 20px; - } - input[type="checkbox"], - input[type="radio"] { - border: 1px solid #ccc; - } - .form-horizontal .control-label { - float: none; - width: auto; - padding-top: 0; - text-align: left; - } - .form-horizontal .controls { - margin-left: 0; - } - .form-horizontal .control-list { - padding-top: 0; - } - .form-horizontal .form-actions { - padding-left: 10px; - padding-right: 10px; - } - .media .pull-left, - .media .pull-right { - float: none; - display: block; - margin-bottom: 10px; - } - .media-object { - margin-right: 0; - margin-left: 0; - } - .modal { - top: 10px; - left: 10px; - right: 10px; - } - .modal-header .close { - padding: 10px; - margin: -10px; - } - .carousel-caption { - position: static; - } -} -@media (max-width: 979px) { - body { - padding-top: 0; - } - .navbar-fixed-top, - .navbar-fixed-bottom { - position: static; - } - .navbar-fixed-top { - margin-bottom: 20px; - } - .navbar-fixed-bottom { - margin-top: 20px; - } - .navbar-fixed-top .navbar-inner, - .navbar-fixed-bottom .navbar-inner { - padding: 5px; - } - .navbar .container { - width: auto; - padding: 0; - } - .navbar .brand { - padding-left: 10px; - padding-right: 10px; - margin: 0 0 0 -5px; - } - .nav-collapse { - clear: both; - } - .nav-collapse .nav { - float: none; - margin: 0 0 10px; - } - .nav-collapse .nav > li { - float: none; - } - .nav-collapse .nav > li > a { - margin-bottom: 2px; - } - .nav-collapse .nav > .divider-vertical { - display: none; - } - .nav-collapse .nav .nav-header { - color: #777777; - text-shadow: none; - } - .nav-collapse .nav > li > a, - .nav-collapse .dropdown-menu a { - padding: 9px 15px; - font-weight: bold; - color: #777777; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - } - .nav-collapse .btn { - padding: 4px 10px 4px; - font-weight: normal; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - } - .nav-collapse .dropdown-menu li + li a { - margin-bottom: 2px; - } - .nav-collapse .nav > li > a:hover, - .nav-collapse .nav > li > a:focus, - .nav-collapse .dropdown-menu a:hover, - .nav-collapse .dropdown-menu a:focus { - background-color: #f2f2f2; - } - .navbar-inverse .nav-collapse .nav > li > a, - .navbar-inverse .nav-collapse .dropdown-menu a { - color: #999999; - } - .navbar-inverse .nav-collapse .nav > li > a:hover, - .navbar-inverse .nav-collapse .nav > li > a:focus, - .navbar-inverse .nav-collapse .dropdown-menu a:hover, - .navbar-inverse .nav-collapse .dropdown-menu a:focus { - background-color: #111111; - } - .nav-collapse.in .btn-group { - margin-top: 5px; - padding: 0; - } - .nav-collapse .dropdown-menu { - position: static; - top: auto; - left: auto; - float: none; - display: none; - max-width: none; - margin: 0 15px; - padding: 0; - background-color: transparent; - border: none; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; - } - .nav-collapse .open > .dropdown-menu { - display: block; - } - .nav-collapse .dropdown-menu:before, - .nav-collapse .dropdown-menu:after { - display: none; - } - .nav-collapse .dropdown-menu .divider { - display: none; - } - .nav-collapse .nav > li > .dropdown-menu:before, - .nav-collapse .nav > li > .dropdown-menu:after { - display: none; - } - .nav-collapse .navbar-form, - .nav-collapse .navbar-search { - float: none; - padding: 10px 15px; - margin: 10px 0; - border-top: 1px solid #f2f2f2; - border-bottom: 1px solid #f2f2f2; - -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1); - -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1); - box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1); - } - .navbar-inverse .nav-collapse .navbar-form, - .navbar-inverse .nav-collapse .navbar-search { - border-top-color: #111111; - border-bottom-color: #111111; - } - .navbar .nav-collapse .nav.pull-right { - float: none; - margin-left: 0; - } - .nav-collapse, - .nav-collapse.collapse { - overflow: hidden; - height: 0; - } - .navbar .btn-navbar { - display: block; - } - .navbar-static .navbar-inner { - padding-left: 10px; - padding-right: 10px; - } -} -@media (min-width: 979px + 1) { - .nav-collapse.collapse { - height: auto !important; - overflow: visible !important; - } -} - diff --git a/openid-connect-server-webapp/src/main/webapp/resources/bootstrap2/css/bootstrap.css b/openid-connect-server-webapp/src/main/webapp/resources/bootstrap2/css/bootstrap.css deleted file mode 100644 index dd320d684b..0000000000 --- a/openid-connect-server-webapp/src/main/webapp/resources/bootstrap2/css/bootstrap.css +++ /dev/null @@ -1,5236 +0,0 @@ -/*! - * Bootstrap v2.3.2 - * - * Copyright 2013 Twitter, Inc - * Licensed under the Apache License v2.0 - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Designed and built with all the love in the world by @mdo and @fat. - */ -.clearfix { - *zoom: 1; -} -.clearfix:before, -.clearfix:after { - display: table; - content: ""; - line-height: 0; -} -.clearfix:after { - clear: both; -} -.hide-text { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0; -} -.input-block-level { - display: block; - width: 100%; - min-height: 30px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -nav, -section { - display: block; -} -audio, -canvas, -video { - display: inline-block; - *display: inline; - *zoom: 1; -} -audio:not([controls]) { - display: none; -} -html { - font-size: 100%; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} -a:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -a:hover, -a:active { - outline: 0; -} -sub, -sup { - position: relative; - font-size: 75%; - line-height: 0; - vertical-align: baseline; -} -sup { - top: -0.5em; -} -sub { - bottom: -0.25em; -} -img { - /* Responsive images (ensure images don't scale beyond their parents) */ - max-width: 100%; - /* Part 1: Set a maxium relative to the parent */ - width: auto\9; - /* IE7-8 need help adjusting responsive images */ - height: auto; - /* Part 2: Scale the height according to the width, otherwise you get stretching */ - vertical-align: middle; - border: 0; - -ms-interpolation-mode: bicubic; -} -#map_canvas img, -.google-maps img { - max-width: none; -} -button, -input, -select, -textarea { - margin: 0; - font-size: 100%; - vertical-align: middle; -} -button, -input { - *overflow: visible; - line-height: normal; -} -button::-moz-focus-inner, -input::-moz-focus-inner { - padding: 0; - border: 0; -} -button, -html input[type="button"], -input[type="reset"], -input[type="submit"] { - -webkit-appearance: button; - cursor: pointer; -} -label, -select, -button, -input[type="button"], -input[type="reset"], -input[type="submit"], -input[type="radio"], -input[type="checkbox"] { - cursor: pointer; -} -input[type="search"] { - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; - -webkit-appearance: textfield; -} -input[type="search"]::-webkit-search-decoration, -input[type="search"]::-webkit-search-cancel-button { - -webkit-appearance: none; -} -textarea { - overflow: auto; - vertical-align: top; -} -@media print { - * { - text-shadow: none !important; - color: #000 !important; - background: transparent !important; - box-shadow: none !important; - } - a, - a:visited { - text-decoration: underline; - } - a[href]:after { - content: " (" attr(href) ")"; - } - abbr[title]:after { - content: " (" attr(title) ")"; - } - .ir a:after, - a[href^="javascript:"]:after, - a[href^="#"]:after { - content: ""; - } - pre, - blockquote { - border: 1px solid #999; - page-break-inside: avoid; - } - thead { - display: table-header-group; - } - tr, - img { - page-break-inside: avoid; - } - img { - max-width: 100% !important; - } - @page { - margin: 0.5cm; - } - p, - h2, - h3 { - orphans: 3; - widows: 3; - } - h2, - h3 { - page-break-after: avoid; - } -} -body { - margin: 0; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 20px; - color: #333333; - background-color: #ffffff; -} -a { - color: #0088cc; - text-decoration: none; -} -a:hover, -a:focus { - color: #005580; - text-decoration: underline; -} -.img-rounded { - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} -.img-polaroid { - padding: 4px; - background-color: #fff; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.2); - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); -} -.img-circle { - -webkit-border-radius: 500px; - -moz-border-radius: 500px; - border-radius: 500px; -} -.row { - margin-left: -20px; - *zoom: 1; -} -.row:before, -.row:after { - display: table; - content: ""; - line-height: 0; -} -.row:after { - clear: both; -} -[class*="span"] { - float: left; - min-height: 1px; - margin-left: 20px; -} -.container, -.navbar-static-top .container, -.navbar-fixed-top .container, -.navbar-fixed-bottom .container { - width: 940px; -} -.span12 { - width: 940px; -} -.span11 { - width: 860px; -} -.span10 { - width: 780px; -} -.span9 { - width: 700px; -} -.span8 { - width: 620px; -} -.span7 { - width: 540px; -} -.span6 { - width: 460px; -} -.span5 { - width: 380px; -} -.span4 { - width: 300px; -} -.span3 { - width: 220px; -} -.span2 { - width: 140px; -} -.span1 { - width: 60px; -} -.offset12 { - margin-left: 980px; -} -.offset11 { - margin-left: 900px; -} -.offset10 { - margin-left: 820px; -} -.offset9 { - margin-left: 740px; -} -.offset8 { - margin-left: 660px; -} -.offset7 { - margin-left: 580px; -} -.offset6 { - margin-left: 500px; -} -.offset5 { - margin-left: 420px; -} -.offset4 { - margin-left: 340px; -} -.offset3 { - margin-left: 260px; -} -.offset2 { - margin-left: 180px; -} -.offset1 { - margin-left: 100px; -} -.row-fluid { - width: 100%; - *zoom: 1; -} -.row-fluid:before, -.row-fluid:after { - display: table; - content: ""; - line-height: 0; -} -.row-fluid:after { - clear: both; -} -.row-fluid [class*="span"] { - display: block; - width: 100%; - min-height: 30px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - float: left; - margin-left: 2.12765957%; - *margin-left: 2.07446809%; -} -.row-fluid [class*="span"]:first-child { - margin-left: 0; -} -.row-fluid .controls-row [class*="span"] + [class*="span"] { - margin-left: 2.12765957%; -} -.row-fluid .span12 { - width: 100%; - *width: 99.94680851%; -} -.row-fluid .span11 { - width: 91.4893617%; - *width: 91.43617021%; -} -.row-fluid .span10 { - width: 82.9787234%; - *width: 82.92553191%; -} -.row-fluid .span9 { - width: 74.46808511%; - *width: 74.41489362%; -} -.row-fluid .span8 { - width: 65.95744681%; - *width: 65.90425532%; -} -.row-fluid .span7 { - width: 57.44680851%; - *width: 57.39361702%; -} -.row-fluid .span6 { - width: 48.93617021%; - *width: 48.88297872%; -} -.row-fluid .span5 { - width: 40.42553191%; - *width: 40.37234043%; -} -.row-fluid .span4 { - width: 31.91489362%; - *width: 31.86170213%; -} -.row-fluid .span3 { - width: 23.40425532%; - *width: 23.35106383%; -} -.row-fluid .span2 { - width: 14.89361702%; - *width: 14.84042553%; -} -.row-fluid .span1 { - width: 6.38297872%; - *width: 6.32978723%; -} -.row-fluid .offset12 { - margin-left: 104.25531915%; - *margin-left: 104.14893617%; -} -.row-fluid .offset12:first-child { - margin-left: 102.12765957%; - *margin-left: 102.0212766%; -} -.row-fluid .offset11 { - margin-left: 95.74468085%; - *margin-left: 95.63829787%; -} -.row-fluid .offset11:first-child { - margin-left: 93.61702128%; - *margin-left: 93.5106383%; -} -.row-fluid .offset10 { - margin-left: 87.23404255%; - *margin-left: 87.12765957%; -} -.row-fluid .offset10:first-child { - margin-left: 85.10638298%; - *margin-left: 85%; -} -.row-fluid .offset9 { - margin-left: 78.72340426%; - *margin-left: 78.61702128%; -} -.row-fluid .offset9:first-child { - margin-left: 76.59574468%; - *margin-left: 76.4893617%; -} -.row-fluid .offset8 { - margin-left: 70.21276596%; - *margin-left: 70.10638298%; -} -.row-fluid .offset8:first-child { - margin-left: 68.08510638%; - *margin-left: 67.9787234%; -} -.row-fluid .offset7 { - margin-left: 61.70212766%; - *margin-left: 61.59574468%; -} -.row-fluid .offset7:first-child { - margin-left: 59.57446809%; - *margin-left: 59.46808511%; -} -.row-fluid .offset6 { - margin-left: 53.19148936%; - *margin-left: 53.08510638%; -} -.row-fluid .offset6:first-child { - margin-left: 51.06382979%; - *margin-left: 50.95744681%; -} -.row-fluid .offset5 { - margin-left: 44.68085106%; - *margin-left: 44.57446809%; -} -.row-fluid .offset5:first-child { - margin-left: 42.55319149%; - *margin-left: 42.44680851%; -} -.row-fluid .offset4 { - margin-left: 36.17021277%; - *margin-left: 36.06382979%; -} -.row-fluid .offset4:first-child { - margin-left: 34.04255319%; - *margin-left: 33.93617021%; -} -.row-fluid .offset3 { - margin-left: 27.65957447%; - *margin-left: 27.55319149%; -} -.row-fluid .offset3:first-child { - margin-left: 25.53191489%; - *margin-left: 25.42553191%; -} -.row-fluid .offset2 { - margin-left: 19.14893617%; - *margin-left: 19.04255319%; -} -.row-fluid .offset2:first-child { - margin-left: 17.0212766%; - *margin-left: 16.91489362%; -} -.row-fluid .offset1 { - margin-left: 10.63829787%; - *margin-left: 10.53191489%; -} -.row-fluid .offset1:first-child { - margin-left: 8.5106383%; - *margin-left: 8.40425532%; -} -[class*="span"].hide, -.row-fluid [class*="span"].hide { - display: none; -} -[class*="span"].pull-right, -.row-fluid [class*="span"].pull-right { - float: right; -} -.container { - margin-right: auto; - margin-left: auto; - *zoom: 1; -} -.container:before, -.container:after { - display: table; - content: ""; - line-height: 0; -} -.container:after { - clear: both; -} -.container-fluid { - padding-right: 20px; - padding-left: 20px; - *zoom: 1; -} -.container-fluid:before, -.container-fluid:after { - display: table; - content: ""; - line-height: 0; -} -.container-fluid:after { - clear: both; -} -p { - margin: 0 0 10px; -} -.lead { - margin-bottom: 20px; - font-size: 21px; - font-weight: 200; - line-height: 30px; -} -small { - font-size: 85%; -} -strong { - font-weight: bold; -} -em { - font-style: italic; -} -cite { - font-style: normal; -} -.muted { - color: #999999; -} -a.muted:hover, -a.muted:focus { - color: #808080; -} -.text-warning { - color: #c09853; -} -a.text-warning:hover, -a.text-warning:focus { - color: #a47e3c; -} -.text-error { - color: #b94a48; -} -a.text-error:hover, -a.text-error:focus { - color: #953b39; -} -.text-info { - color: #3a87ad; -} -a.text-info:hover, -a.text-info:focus { - color: #2d6987; -} -.text-success { - color: #468847; -} -a.text-success:hover, -a.text-success:focus { - color: #356635; -} -.text-left { - text-align: left; -} -.text-right { - text-align: right; -} -.text-center { - text-align: center; -} -h1, -h2, -h3, -h4, -h5, -h6 { - margin: 10px 0; - font-family: inherit; - font-weight: bold; - line-height: 20px; - color: inherit; - text-rendering: optimizelegibility; -} -h1 small, -h2 small, -h3 small, -h4 small, -h5 small, -h6 small { - font-weight: normal; - line-height: 1; - color: #999999; -} -h1, -h2, -h3 { - line-height: 40px; -} -h1 { - font-size: 38.5px; -} -h2 { - font-size: 31.5px; -} -h3 { - font-size: 24.5px; -} -h4 { - font-size: 17.5px; -} -h5 { - font-size: 14px; -} -h6 { - font-size: 11.9px; -} -h1 small { - font-size: 24.5px; -} -h2 small { - font-size: 17.5px; -} -h3 small { - font-size: 14px; -} -h4 small { - font-size: 14px; -} -.page-header { - padding-bottom: 9px; - margin: 20px 0 30px; - border-bottom: 1px solid #eeeeee; -} -ul, -ol { - padding: 0; - margin: 0 0 10px 25px; -} -ul ul, -ul ol, -ol ol, -ol ul { - margin-bottom: 0; -} -li { - line-height: 20px; -} -ul.unstyled, -ol.unstyled { - margin-left: 0; - list-style: none; -} -ul.inline, -ol.inline { - margin-left: 0; - list-style: none; -} -ul.inline > li, -ol.inline > li { - display: inline-block; - *display: inline; - /* IE7 inline-block hack */ - *zoom: 1; - padding-left: 5px; - padding-right: 5px; -} -dl { - margin-bottom: 20px; -} -dt, -dd { - line-height: 20px; -} -dt { - font-weight: bold; -} -dd { - margin-left: 10px; -} -.dl-horizontal { - *zoom: 1; -} -.dl-horizontal:before, -.dl-horizontal:after { - display: table; - content: ""; - line-height: 0; -} -.dl-horizontal:after { - clear: both; -} -.dl-horizontal dt { - float: left; - width: 160px; - clear: left; - text-align: right; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} -.dl-horizontal dd { - margin-left: 180px; -} -hr { - margin: 20px 0; - border: 0; - border-top: 1px solid #eeeeee; - border-bottom: 1px solid #ffffff; -} -abbr[title], -abbr[data-original-title] { - cursor: help; - border-bottom: 1px dotted #999999; -} -abbr.initialism { - font-size: 90%; - text-transform: uppercase; -} -blockquote { - padding: 0 0 0 15px; - margin: 0 0 20px; - border-left: 5px solid #eeeeee; -} -blockquote p { - margin-bottom: 0; - font-size: 17.5px; - font-weight: 300; - line-height: 1.25; -} -blockquote small { - display: block; - line-height: 20px; - color: #999999; -} -blockquote small:before { - content: '\2014 \00A0'; -} -blockquote.pull-right { - float: right; - padding-right: 15px; - padding-left: 0; - border-right: 5px solid #eeeeee; - border-left: 0; -} -blockquote.pull-right p, -blockquote.pull-right small { - text-align: right; -} -blockquote.pull-right small:before { - content: ''; -} -blockquote.pull-right small:after { - content: '\00A0 \2014'; -} -q:before, -q:after, -blockquote:before, -blockquote:after { - content: ""; -} -address { - display: block; - margin-bottom: 20px; - font-style: normal; - line-height: 20px; -} -code, -pre { - padding: 0 3px 2px; - font-family: Monaco, Menlo, Consolas, "Courier New", monospace; - font-size: 12px; - color: #333333; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} -code { - padding: 2px 4px; - color: #d14; - background-color: #f7f7f9; - border: 1px solid #e1e1e8; - white-space: nowrap; -} -pre { - display: block; - padding: 9.5px; - margin: 0 0 10px; - font-size: 13px; - line-height: 20px; - word-break: break-all; - word-wrap: break-word; - white-space: pre; - white-space: pre-wrap; - background-color: #f5f5f5; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.15); - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} -pre.prettyprint { - margin-bottom: 20px; -} -pre code { - padding: 0; - color: inherit; - white-space: pre; - white-space: pre-wrap; - background-color: transparent; - border: 0; -} -.pre-scrollable { - max-height: 340px; - overflow-y: scroll; -} -form { - margin: 0 0 20px; -} -fieldset { - padding: 0; - margin: 0; - border: 0; -} -legend { - display: block; - width: 100%; - padding: 0; - margin-bottom: 20px; - font-size: 21px; - line-height: 40px; - color: #333333; - border: 0; - border-bottom: 1px solid #e5e5e5; -} -legend small { - font-size: 15px; - color: #999999; -} -label, -input, -button, -select, -textarea { - font-size: 14px; - font-weight: normal; - line-height: 20px; -} -input, -button, -select, -textarea { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; -} -label { - display: block; - margin-bottom: 5px; -} -select, -textarea, -input[type="text"], -input[type="password"], -input[type="datetime"], -input[type="datetime-local"], -input[type="date"], -input[type="month"], -input[type="time"], -input[type="week"], -input[type="number"], -input[type="email"], -input[type="url"], -input[type="search"], -input[type="tel"], -input[type="color"], -.uneditable-input { - display: inline-block; - height: 20px; - padding: 4px 6px; - margin-bottom: 10px; - font-size: 14px; - line-height: 20px; - color: #555555; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - vertical-align: middle; -} -input, -textarea, -.uneditable-input { - width: 206px; -} -textarea { - height: auto; -} -textarea, -input[type="text"], -input[type="password"], -input[type="datetime"], -input[type="datetime-local"], -input[type="date"], -input[type="month"], -input[type="time"], -input[type="week"], -input[type="number"], -input[type="email"], -input[type="url"], -input[type="search"], -input[type="tel"], -input[type="color"], -.uneditable-input { - background-color: #ffffff; - border: 1px solid #cccccc; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -webkit-transition: border linear .2s, box-shadow linear .2s; - -moz-transition: border linear .2s, box-shadow linear .2s; - -o-transition: border linear .2s, box-shadow linear .2s; - transition: border linear .2s, box-shadow linear .2s; -} -textarea:focus, -input[type="text"]:focus, -input[type="password"]:focus, -input[type="datetime"]:focus, -input[type="datetime-local"]:focus, -input[type="date"]:focus, -input[type="month"]:focus, -input[type="time"]:focus, -input[type="week"]:focus, -input[type="number"]:focus, -input[type="email"]:focus, -input[type="url"]:focus, -input[type="search"]:focus, -input[type="tel"]:focus, -input[type="color"]:focus, -.uneditable-input:focus { - border-color: rgba(82, 168, 236, 0.8); - outline: 0; - outline: thin dotted \9; - /* IE6-9 */ - -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6); - -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6); - box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6); -} -input[type="radio"], -input[type="checkbox"] { - margin: 4px 0 0; - *margin-top: 0; - /* IE7 */ - margin-top: 1px \9; - /* IE8-9 */ - line-height: normal; -} -input[type="file"], -input[type="image"], -input[type="submit"], -input[type="reset"], -input[type="button"], -input[type="radio"], -input[type="checkbox"] { - width: auto; -} -select, -input[type="file"] { - height: 30px; - /* In IE7, the height of the select element cannot be changed by height, only font-size */ - *margin-top: 4px; - /* For IE7, add top margin to align select with labels */ - line-height: 30px; -} -select { - width: 220px; - border: 1px solid #cccccc; - background-color: #ffffff; -} -select[multiple], -select[size] { - height: auto; -} -select:focus, -input[type="file"]:focus, -input[type="radio"]:focus, -input[type="checkbox"]:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -.uneditable-input, -.uneditable-textarea { - color: #999999; - background-color: #fcfcfc; - border-color: #cccccc; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); - cursor: not-allowed; -} -.uneditable-input { - overflow: hidden; - white-space: nowrap; -} -.uneditable-textarea { - width: auto; - height: auto; -} -input:-moz-placeholder, -textarea:-moz-placeholder { - color: #999999; -} -input:-ms-input-placeholder, -textarea:-ms-input-placeholder { - color: #999999; -} -input::-webkit-input-placeholder, -textarea::-webkit-input-placeholder { - color: #999999; -} -.radio, -.checkbox { - min-height: 20px; - padding-left: 20px; -} -.radio input[type="radio"], -.checkbox input[type="checkbox"] { - float: left; - margin-left: -20px; -} -.controls > .radio:first-child, -.controls > .checkbox:first-child { - padding-top: 5px; -} -.radio.inline, -.checkbox.inline { - display: inline-block; - padding-top: 5px; - margin-bottom: 0; - vertical-align: middle; -} -.radio.inline + .radio.inline, -.checkbox.inline + .checkbox.inline { - margin-left: 10px; -} -.input-mini { - width: 60px; -} -.input-small { - width: 90px; -} -.input-medium { - width: 150px; -} -.input-large { - width: 210px; -} -.input-xlarge { - width: 270px; -} -.input-xxlarge { - width: 530px; -} -input[class*="span"], -select[class*="span"], -textarea[class*="span"], -.uneditable-input[class*="span"], -.row-fluid input[class*="span"], -.row-fluid select[class*="span"], -.row-fluid textarea[class*="span"], -.row-fluid .uneditable-input[class*="span"] { - float: none; - margin-left: 0; -} -.input-append input[class*="span"], -.input-append .uneditable-input[class*="span"], -.input-prepend input[class*="span"], -.input-prepend .uneditable-input[class*="span"], -.row-fluid input[class*="span"], -.row-fluid select[class*="span"], -.row-fluid textarea[class*="span"], -.row-fluid .uneditable-input[class*="span"], -.row-fluid .input-prepend [class*="span"], -.row-fluid .input-append [class*="span"] { - display: inline-block; -} -input, -textarea, -.uneditable-input { - margin-left: 0; -} -.controls-row [class*="span"] + [class*="span"] { - margin-left: 20px; -} -input.span12, -textarea.span12, -.uneditable-input.span12 { - width: 926px; -} -input.span11, -textarea.span11, -.uneditable-input.span11 { - width: 846px; -} -input.span10, -textarea.span10, -.uneditable-input.span10 { - width: 766px; -} -input.span9, -textarea.span9, -.uneditable-input.span9 { - width: 686px; -} -input.span8, -textarea.span8, -.uneditable-input.span8 { - width: 606px; -} -input.span7, -textarea.span7, -.uneditable-input.span7 { - width: 526px; -} -input.span6, -textarea.span6, -.uneditable-input.span6 { - width: 446px; -} -input.span5, -textarea.span5, -.uneditable-input.span5 { - width: 366px; -} -input.span4, -textarea.span4, -.uneditable-input.span4 { - width: 286px; -} -input.span3, -textarea.span3, -.uneditable-input.span3 { - width: 206px; -} -input.span2, -textarea.span2, -.uneditable-input.span2 { - width: 126px; -} -input.span1, -textarea.span1, -.uneditable-input.span1 { - width: 46px; -} -.controls-row { - *zoom: 1; -} -.controls-row:before, -.controls-row:after { - display: table; - content: ""; - line-height: 0; -} -.controls-row:after { - clear: both; -} -.controls-row [class*="span"], -.row-fluid .controls-row [class*="span"] { - float: left; -} -.controls-row .checkbox[class*="span"], -.controls-row .radio[class*="span"] { - padding-top: 5px; -} -input[disabled], -select[disabled], -textarea[disabled], -input[readonly], -select[readonly], -textarea[readonly] { - cursor: not-allowed; - background-color: #eeeeee; -} -input[type="radio"][disabled], -input[type="checkbox"][disabled], -input[type="radio"][readonly], -input[type="checkbox"][readonly] { - background-color: transparent; -} -.control-group.warning .control-label, -.control-group.warning .help-block, -.control-group.warning .help-inline { - color: #c09853; -} -.control-group.warning .checkbox, -.control-group.warning .radio, -.control-group.warning input, -.control-group.warning select, -.control-group.warning textarea { - color: #c09853; -} -.control-group.warning input, -.control-group.warning select, -.control-group.warning textarea { - border-color: #c09853; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} -.control-group.warning input:focus, -.control-group.warning select:focus, -.control-group.warning textarea:focus { - border-color: #a47e3c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; -} -.control-group.warning .input-prepend .add-on, -.control-group.warning .input-append .add-on { - color: #c09853; - background-color: #fcf8e3; - border-color: #c09853; -} -.control-group.error .control-label, -.control-group.error .help-block, -.control-group.error .help-inline { - color: #b94a48; -} -.control-group.error .checkbox, -.control-group.error .radio, -.control-group.error input, -.control-group.error select, -.control-group.error textarea { - color: #b94a48; -} -.control-group.error input, -.control-group.error select, -.control-group.error textarea { - border-color: #b94a48; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} -.control-group.error input:focus, -.control-group.error select:focus, -.control-group.error textarea:focus { - border-color: #953b39; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; -} -.control-group.error .input-prepend .add-on, -.control-group.error .input-append .add-on { - color: #b94a48; - background-color: #f2dede; - border-color: #b94a48; -} -.control-group.success .control-label, -.control-group.success .help-block, -.control-group.success .help-inline { - color: #468847; -} -.control-group.success .checkbox, -.control-group.success .radio, -.control-group.success input, -.control-group.success select, -.control-group.success textarea { - color: #468847; -} -.control-group.success input, -.control-group.success select, -.control-group.success textarea { - border-color: #468847; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} -.control-group.success input:focus, -.control-group.success select:focus, -.control-group.success textarea:focus { - border-color: #356635; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; -} -.control-group.success .input-prepend .add-on, -.control-group.success .input-append .add-on { - color: #468847; - background-color: #dff0d8; - border-color: #468847; -} -.control-group.info .control-label, -.control-group.info .help-block, -.control-group.info .help-inline { - color: #3a87ad; -} -.control-group.info .checkbox, -.control-group.info .radio, -.control-group.info input, -.control-group.info select, -.control-group.info textarea { - color: #3a87ad; -} -.control-group.info input, -.control-group.info select, -.control-group.info textarea { - border-color: #3a87ad; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} -.control-group.info input:focus, -.control-group.info select:focus, -.control-group.info textarea:focus { - border-color: #2d6987; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; -} -.control-group.info .input-prepend .add-on, -.control-group.info .input-append .add-on { - color: #3a87ad; - background-color: #d9edf7; - border-color: #3a87ad; -} -input:focus:invalid, -textarea:focus:invalid, -select:focus:invalid { - color: #b94a48; - border-color: #ee5f5b; -} -input:focus:invalid:focus, -textarea:focus:invalid:focus, -select:focus:invalid:focus { - border-color: #e9322d; - -webkit-box-shadow: 0 0 6px #f8b9b7; - -moz-box-shadow: 0 0 6px #f8b9b7; - box-shadow: 0 0 6px #f8b9b7; -} -.form-actions { - padding: 19px 20px 20px; - margin-top: 20px; - margin-bottom: 20px; - background-color: #f5f5f5; - border-top: 1px solid #e5e5e5; - *zoom: 1; -} -.form-actions:before, -.form-actions:after { - display: table; - content: ""; - line-height: 0; -} -.form-actions:after { - clear: both; -} -.help-block, -.help-inline { - color: #595959; -} -.help-block { - display: block; - margin-bottom: 10px; -} -.help-inline { - display: inline-block; - *display: inline; - /* IE7 inline-block hack */ - *zoom: 1; - vertical-align: middle; - padding-left: 5px; -} -.input-append, -.input-prepend { - display: inline-block; - margin-bottom: 10px; - vertical-align: middle; - font-size: 0; - white-space: nowrap; -} -.input-append input, -.input-prepend input, -.input-append select, -.input-prepend select, -.input-append .uneditable-input, -.input-prepend .uneditable-input, -.input-append .dropdown-menu, -.input-prepend .dropdown-menu, -.input-append .popover, -.input-prepend .popover { - font-size: 14px; -} -.input-append input, -.input-prepend input, -.input-append select, -.input-prepend select, -.input-append .uneditable-input, -.input-prepend .uneditable-input { - position: relative; - margin-bottom: 0; - *margin-left: 0; - vertical-align: top; - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} -.input-append input:focus, -.input-prepend input:focus, -.input-append select:focus, -.input-prepend select:focus, -.input-append .uneditable-input:focus, -.input-prepend .uneditable-input:focus { - z-index: 2; -} -.input-append .add-on, -.input-prepend .add-on { - display: inline-block; - width: auto; - height: 20px; - min-width: 16px; - padding: 4px 5px; - font-size: 14px; - font-weight: normal; - line-height: 20px; - text-align: center; - text-shadow: 0 1px 0 #ffffff; - background-color: #eeeeee; - border: 1px solid #ccc; -} -.input-append .add-on, -.input-prepend .add-on, -.input-append .btn, -.input-prepend .btn, -.input-append .btn-group > .dropdown-toggle, -.input-prepend .btn-group > .dropdown-toggle { - vertical-align: top; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} -.input-append .active, -.input-prepend .active { - background-color: #a9dba9; - border-color: #46a546; -} -.input-prepend .add-on, -.input-prepend .btn { - margin-right: -1px; -} -.input-prepend .add-on:first-child, -.input-prepend .btn:first-child { - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; -} -.input-append input, -.input-append select, -.input-append .uneditable-input { - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; -} -.input-append input + .btn-group .btn:last-child, -.input-append select + .btn-group .btn:last-child, -.input-append .uneditable-input + .btn-group .btn:last-child { - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} -.input-append .add-on, -.input-append .btn, -.input-append .btn-group { - margin-left: -1px; -} -.input-append .add-on:last-child, -.input-append .btn:last-child, -.input-append .btn-group:last-child > .dropdown-toggle { - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} -.input-prepend.input-append input, -.input-prepend.input-append select, -.input-prepend.input-append .uneditable-input { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} -.input-prepend.input-append input + .btn-group .btn, -.input-prepend.input-append select + .btn-group .btn, -.input-prepend.input-append .uneditable-input + .btn-group .btn { - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} -.input-prepend.input-append .add-on:first-child, -.input-prepend.input-append .btn:first-child { - margin-right: -1px; - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; -} -.input-prepend.input-append .add-on:last-child, -.input-prepend.input-append .btn:last-child { - margin-left: -1px; - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} -.input-prepend.input-append .btn-group:first-child { - margin-left: 0; -} -input.search-query { - padding-right: 14px; - padding-right: 4px \9; - padding-left: 14px; - padding-left: 4px \9; - /* IE7-8 doesn't have border-radius, so don't indent the padding */ - margin-bottom: 0; - -webkit-border-radius: 15px; - -moz-border-radius: 15px; - border-radius: 15px; -} -/* Allow for input prepend/append in search forms */ -.form-search .input-append .search-query, -.form-search .input-prepend .search-query { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} -.form-search .input-append .search-query { - -webkit-border-radius: 14px 0 0 14px; - -moz-border-radius: 14px 0 0 14px; - border-radius: 14px 0 0 14px; -} -.form-search .input-append .btn { - -webkit-border-radius: 0 14px 14px 0; - -moz-border-radius: 0 14px 14px 0; - border-radius: 0 14px 14px 0; -} -.form-search .input-prepend .search-query { - -webkit-border-radius: 0 14px 14px 0; - -moz-border-radius: 0 14px 14px 0; - border-radius: 0 14px 14px 0; -} -.form-search .input-prepend .btn { - -webkit-border-radius: 14px 0 0 14px; - -moz-border-radius: 14px 0 0 14px; - border-radius: 14px 0 0 14px; -} -.form-search input, -.form-inline input, -.form-horizontal input, -.form-search textarea, -.form-inline textarea, -.form-horizontal textarea, -.form-search select, -.form-inline select, -.form-horizontal select, -.form-search .help-inline, -.form-inline .help-inline, -.form-horizontal .help-inline, -.form-search .uneditable-input, -.form-inline .uneditable-input, -.form-horizontal .uneditable-input, -.form-search .input-prepend, -.form-inline .input-prepend, -.form-horizontal .input-prepend, -.form-search .input-append, -.form-inline .input-append, -.form-horizontal .input-append { - display: inline-block; - *display: inline; - /* IE7 inline-block hack */ - *zoom: 1; - margin-bottom: 0; - vertical-align: middle; -} -.form-search .hide, -.form-inline .hide, -.form-horizontal .hide { - display: none; -} -.form-search label, -.form-inline label, -.form-search .btn-group, -.form-inline .btn-group { - display: inline-block; -} -.form-search .input-append, -.form-inline .input-append, -.form-search .input-prepend, -.form-inline .input-prepend { - margin-bottom: 0; -} -.form-search .radio, -.form-search .checkbox, -.form-inline .radio, -.form-inline .checkbox { - padding-left: 0; - margin-bottom: 0; - vertical-align: middle; -} -.form-search .radio input[type="radio"], -.form-search .checkbox input[type="checkbox"], -.form-inline .radio input[type="radio"], -.form-inline .checkbox input[type="checkbox"] { - float: left; - margin-right: 3px; - margin-left: 0; -} -.control-group { - margin-bottom: 10px; -} -legend + .control-group { - margin-top: 20px; - -webkit-margin-top-collapse: separate; -} -.form-horizontal .control-group { - margin-bottom: 20px; - *zoom: 1; -} -.form-horizontal .control-group:before, -.form-horizontal .control-group:after { - display: table; - content: ""; - line-height: 0; -} -.form-horizontal .control-group:after { - clear: both; -} -.form-horizontal .control-label { - float: left; - width: 160px; - padding-top: 5px; - text-align: right; -} -.form-horizontal .controls { - *display: inline-block; - *padding-left: 20px; - margin-left: 180px; - *margin-left: 0; -} -.form-horizontal .controls:first-child { - *padding-left: 180px; -} -.form-horizontal .help-block { - margin-bottom: 0; -} -.form-horizontal input + .help-block, -.form-horizontal select + .help-block, -.form-horizontal textarea + .help-block, -.form-horizontal .uneditable-input + .help-block, -.form-horizontal .input-prepend + .help-block, -.form-horizontal .input-append + .help-block { - margin-top: 10px; -} -.form-horizontal .form-actions { - padding-left: 180px; -} -table { - max-width: 100%; - background-color: transparent; - border-collapse: collapse; - border-spacing: 0; -} -.table { - width: 100%; - margin-bottom: 20px; -} -.table th, -.table td { - padding: 8px; - line-height: 20px; - text-align: left; - vertical-align: top; - border-top: 1px solid #dddddd; -} -.table th { - font-weight: bold; -} -.table thead th { - vertical-align: bottom; -} -.table caption + thead tr:first-child th, -.table caption + thead tr:first-child td, -.table colgroup + thead tr:first-child th, -.table colgroup + thead tr:first-child td, -.table thead:first-child tr:first-child th, -.table thead:first-child tr:first-child td { - border-top: 0; -} -.table tbody + tbody { - border-top: 2px solid #dddddd; -} -.table .table { - background-color: #ffffff; -} -.table-condensed th, -.table-condensed td { - padding: 4px 5px; -} -.table-bordered { - border: 1px solid #dddddd; - border-collapse: separate; - *border-collapse: collapse; - border-left: 0; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} -.table-bordered th, -.table-bordered td { - border-left: 1px solid #dddddd; -} -.table-bordered caption + thead tr:first-child th, -.table-bordered caption + tbody tr:first-child th, -.table-bordered caption + tbody tr:first-child td, -.table-bordered colgroup + thead tr:first-child th, -.table-bordered colgroup + tbody tr:first-child th, -.table-bordered colgroup + tbody tr:first-child td, -.table-bordered thead:first-child tr:first-child th, -.table-bordered tbody:first-child tr:first-child th, -.table-bordered tbody:first-child tr:first-child td { - border-top: 0; -} -.table-bordered thead:first-child tr:first-child > th:first-child, -.table-bordered tbody:first-child tr:first-child > td:first-child, -.table-bordered tbody:first-child tr:first-child > th:first-child { - -webkit-border-top-left-radius: 4px; - -moz-border-radius-topleft: 4px; - border-top-left-radius: 4px; -} -.table-bordered thead:first-child tr:first-child > th:last-child, -.table-bordered tbody:first-child tr:first-child > td:last-child, -.table-bordered tbody:first-child tr:first-child > th:last-child { - -webkit-border-top-right-radius: 4px; - -moz-border-radius-topright: 4px; - border-top-right-radius: 4px; -} -.table-bordered thead:last-child tr:last-child > th:first-child, -.table-bordered tbody:last-child tr:last-child > td:first-child, -.table-bordered tbody:last-child tr:last-child > th:first-child, -.table-bordered tfoot:last-child tr:last-child > td:first-child, -.table-bordered tfoot:last-child tr:last-child > th:first-child { - -webkit-border-bottom-left-radius: 4px; - -moz-border-radius-bottomleft: 4px; - border-bottom-left-radius: 4px; -} -.table-bordered thead:last-child tr:last-child > th:last-child, -.table-bordered tbody:last-child tr:last-child > td:last-child, -.table-bordered tbody:last-child tr:last-child > th:last-child, -.table-bordered tfoot:last-child tr:last-child > td:last-child, -.table-bordered tfoot:last-child tr:last-child > th:last-child { - -webkit-border-bottom-right-radius: 4px; - -moz-border-radius-bottomright: 4px; - border-bottom-right-radius: 4px; -} -.table-bordered tfoot + tbody:last-child tr:last-child td:first-child { - -webkit-border-bottom-left-radius: 0; - -moz-border-radius-bottomleft: 0; - border-bottom-left-radius: 0; -} -.table-bordered tfoot + tbody:last-child tr:last-child td:last-child { - -webkit-border-bottom-right-radius: 0; - -moz-border-radius-bottomright: 0; - border-bottom-right-radius: 0; -} -.table-bordered caption + thead tr:first-child th:first-child, -.table-bordered caption + tbody tr:first-child td:first-child, -.table-bordered colgroup + thead tr:first-child th:first-child, -.table-bordered colgroup + tbody tr:first-child td:first-child { - -webkit-border-top-left-radius: 4px; - -moz-border-radius-topleft: 4px; - border-top-left-radius: 4px; -} -.table-bordered caption + thead tr:first-child th:last-child, -.table-bordered caption + tbody tr:first-child td:last-child, -.table-bordered colgroup + thead tr:first-child th:last-child, -.table-bordered colgroup + tbody tr:first-child td:last-child { - -webkit-border-top-right-radius: 4px; - -moz-border-radius-topright: 4px; - border-top-right-radius: 4px; -} -.table-striped tbody > tr:nth-child(odd) > td, -.table-striped tbody > tr:nth-child(odd) > th { - background-color: #f9f9f9; -} -.table-hover tbody tr:hover > td, -.table-hover tbody tr:hover > th { - background-color: #f5f5f5; -} -table td[class*="span"], -table th[class*="span"], -.row-fluid table td[class*="span"], -.row-fluid table th[class*="span"] { - display: table-cell; - float: none; - margin-left: 0; -} -.table td.span1, -.table th.span1 { - float: none; - width: 44px; - margin-left: 0; -} -.table td.span2, -.table th.span2 { - float: none; - width: 124px; - margin-left: 0; -} -.table td.span3, -.table th.span3 { - float: none; - width: 204px; - margin-left: 0; -} -.table td.span4, -.table th.span4 { - float: none; - width: 284px; - margin-left: 0; -} -.table td.span5, -.table th.span5 { - float: none; - width: 364px; - margin-left: 0; -} -.table td.span6, -.table th.span6 { - float: none; - width: 444px; - margin-left: 0; -} -.table td.span7, -.table th.span7 { - float: none; - width: 524px; - margin-left: 0; -} -.table td.span8, -.table th.span8 { - float: none; - width: 604px; - margin-left: 0; -} -.table td.span9, -.table th.span9 { - float: none; - width: 684px; - margin-left: 0; -} -.table td.span10, -.table th.span10 { - float: none; - width: 764px; - margin-left: 0; -} -.table td.span11, -.table th.span11 { - float: none; - width: 844px; - margin-left: 0; -} -.table td.span12, -.table th.span12 { - float: none; - width: 924px; - margin-left: 0; -} -.table tbody tr.success > td { - background-color: #dff0d8; -} -.table tbody tr.error > td { - background-color: #f2dede; -} -.table tbody tr.warning > td { - background-color: #fcf8e3; -} -.table tbody tr.info > td { - background-color: #d9edf7; -} -.table-hover tbody tr.success:hover > td { - background-color: #d0e9c6; -} -.table-hover tbody tr.error:hover > td { - background-color: #ebcccc; -} -.table-hover tbody tr.warning:hover > td { - background-color: #faf2cc; -} -.table-hover tbody tr.info:hover > td { - background-color: #c4e3f3; -} -[class^="icon-"], -[class*=" icon-"] { - display: inline-block; - width: 14px; - height: 14px; - *margin-right: .3em; - line-height: 14px; - vertical-align: text-top; - background-image: url("../img/glyphicons-halflings.png"); - background-position: 14px 14px; - background-repeat: no-repeat; - margin-top: 1px; -} -/* White icons with optional class, or on hover/focus/active states of certain elements */ -.icon-white, -.nav-pills > .active > a > [class^="icon-"], -.nav-pills > .active > a > [class*=" icon-"], -.nav-list > .active > a > [class^="icon-"], -.nav-list > .active > a > [class*=" icon-"], -.navbar-inverse .nav > .active > a > [class^="icon-"], -.navbar-inverse .nav > .active > a > [class*=" icon-"], -.dropdown-menu > li > a:hover > [class^="icon-"], -.dropdown-menu > li > a:focus > [class^="icon-"], -.dropdown-menu > li > a:hover > [class*=" icon-"], -.dropdown-menu > li > a:focus > [class*=" icon-"], -.dropdown-menu > .active > a > [class^="icon-"], -.dropdown-menu > .active > a > [class*=" icon-"], -.dropdown-submenu:hover > a > [class^="icon-"], -.dropdown-submenu:focus > a > [class^="icon-"], -.dropdown-submenu:hover > a > [class*=" icon-"], -.dropdown-submenu:focus > a > [class*=" icon-"] { - background-image: url("../img/glyphicons-halflings-white.png"); -} -.icon-glass { - background-position: 0 0; -} -.icon-music { - background-position: -24px 0; -} -.icon-search { - background-position: -48px 0; -} -.icon-envelope { - background-position: -72px 0; -} -.icon-heart { - background-position: -96px 0; -} -.icon-star { - background-position: -120px 0; -} -.icon-star-empty { - background-position: -144px 0; -} -.icon-user { - background-position: -168px 0; -} -.icon-film { - background-position: -192px 0; -} -.icon-th-large { - background-position: -216px 0; -} -.icon-th { - background-position: -240px 0; -} -.icon-th-list { - background-position: -264px 0; -} -.icon-ok { - background-position: -288px 0; -} -.icon-remove { - background-position: -312px 0; -} -.icon-zoom-in { - background-position: -336px 0; -} -.icon-zoom-out { - background-position: -360px 0; -} -.icon-off { - background-position: -384px 0; -} -.icon-signal { - background-position: -408px 0; -} -.icon-cog { - background-position: -432px 0; -} -.icon-trash { - background-position: -456px 0; -} -.icon-home { - background-position: 0 -24px; -} -.icon-file { - background-position: -24px -24px; -} -.icon-time { - background-position: -48px -24px; -} -.icon-road { - background-position: -72px -24px; -} -.icon-download-alt { - background-position: -96px -24px; -} -.icon-download { - background-position: -120px -24px; -} -.icon-upload { - background-position: -144px -24px; -} -.icon-inbox { - background-position: -168px -24px; -} -.icon-play-circle { - background-position: -192px -24px; -} -.icon-repeat { - background-position: -216px -24px; -} -.icon-refresh { - background-position: -240px -24px; -} -.icon-list-alt { - background-position: -264px -24px; -} -.icon-lock { - background-position: -287px -24px; -} -.icon-flag { - background-position: -312px -24px; -} -.icon-headphones { - background-position: -336px -24px; -} -.icon-volume-off { - background-position: -360px -24px; -} -.icon-volume-down { - background-position: -384px -24px; -} -.icon-volume-up { - background-position: -408px -24px; -} -.icon-qrcode { - background-position: -432px -24px; -} -.icon-barcode { - background-position: -456px -24px; -} -.icon-tag { - background-position: 0 -48px; -} -.icon-tags { - background-position: -25px -48px; -} -.icon-book { - background-position: -48px -48px; -} -.icon-bookmark { - background-position: -72px -48px; -} -.icon-print { - background-position: -96px -48px; -} -.icon-camera { - background-position: -120px -48px; -} -.icon-font { - background-position: -144px -48px; -} -.icon-bold { - background-position: -167px -48px; -} -.icon-italic { - background-position: -192px -48px; -} -.icon-text-height { - background-position: -216px -48px; -} -.icon-text-width { - background-position: -240px -48px; -} -.icon-align-left { - background-position: -264px -48px; -} -.icon-align-center { - background-position: -288px -48px; -} -.icon-align-right { - background-position: -312px -48px; -} -.icon-align-justify { - background-position: -336px -48px; -} -.icon-list { - background-position: -360px -48px; -} -.icon-indent-left { - background-position: -384px -48px; -} -.icon-indent-right { - background-position: -408px -48px; -} -.icon-facetime-video { - background-position: -432px -48px; -} -.icon-picture { - background-position: -456px -48px; -} -.icon-pencil { - background-position: 0 -72px; -} -.icon-map-marker { - background-position: -24px -72px; -} -.icon-adjust { - background-position: -48px -72px; -} -.icon-tint { - background-position: -72px -72px; -} -.icon-edit { - background-position: -96px -72px; -} -.icon-share { - background-position: -120px -72px; -} -.icon-check { - background-position: -144px -72px; -} -.icon-move { - background-position: -168px -72px; -} -.icon-step-backward { - background-position: -192px -72px; -} -.icon-fast-backward { - background-position: -216px -72px; -} -.icon-backward { - background-position: -240px -72px; -} -.icon-play { - background-position: -264px -72px; -} -.icon-pause { - background-position: -288px -72px; -} -.icon-stop { - background-position: -312px -72px; -} -.icon-forward { - background-position: -336px -72px; -} -.icon-fast-forward { - background-position: -360px -72px; -} -.icon-step-forward { - background-position: -384px -72px; -} -.icon-eject { - background-position: -408px -72px; -} -.icon-chevron-left { - background-position: -432px -72px; -} -.icon-chevron-right { - background-position: -456px -72px; -} -.icon-plus-sign { - background-position: 0 -96px; -} -.icon-minus-sign { - background-position: -24px -96px; -} -.icon-remove-sign { - background-position: -48px -96px; -} -.icon-ok-sign { - background-position: -72px -96px; -} -.icon-question-sign { - background-position: -96px -96px; -} -.icon-info-sign { - background-position: -120px -96px; -} -.icon-screenshot { - background-position: -144px -96px; -} -.icon-remove-circle { - background-position: -168px -96px; -} -.icon-ok-circle { - background-position: -192px -96px; -} -.icon-ban-circle { - background-position: -216px -96px; -} -.icon-arrow-left { - background-position: -240px -96px; -} -.icon-arrow-right { - background-position: -264px -96px; -} -.icon-arrow-up { - background-position: -289px -96px; -} -.icon-arrow-down { - background-position: -312px -96px; -} -.icon-share-alt { - background-position: -336px -96px; -} -.icon-resize-full { - background-position: -360px -96px; -} -.icon-resize-small { - background-position: -384px -96px; -} -.icon-plus { - background-position: -408px -96px; -} -.icon-minus { - background-position: -433px -96px; -} -.icon-asterisk { - background-position: -456px -96px; -} -.icon-exclamation-sign { - background-position: 0 -120px; -} -.icon-gift { - background-position: -24px -120px; -} -.icon-leaf { - background-position: -48px -120px; -} -.icon-fire { - background-position: -72px -120px; -} -.icon-eye-open { - background-position: -96px -120px; -} -.icon-eye-close { - background-position: -120px -120px; -} -.icon-warning-sign { - background-position: -144px -120px; -} -.icon-plane { - background-position: -168px -120px; -} -.icon-calendar { - background-position: -192px -120px; -} -.icon-random { - background-position: -216px -120px; - width: 16px; -} -.icon-comment { - background-position: -240px -120px; -} -.icon-magnet { - background-position: -264px -120px; -} -.icon-chevron-up { - background-position: -288px -120px; -} -.icon-chevron-down { - background-position: -313px -119px; -} -.icon-retweet { - background-position: -336px -120px; -} -.icon-shopping-cart { - background-position: -360px -120px; -} -.icon-folder-close { - background-position: -384px -120px; - width: 16px; -} -.icon-folder-open { - background-position: -408px -120px; - width: 16px; -} -.icon-resize-vertical { - background-position: -432px -119px; -} -.icon-resize-horizontal { - background-position: -456px -118px; -} -.icon-hdd { - background-position: 0 -144px; -} -.icon-bullhorn { - background-position: -24px -144px; -} -.icon-bell { - background-position: -48px -144px; -} -.icon-certificate { - background-position: -72px -144px; -} -.icon-thumbs-up { - background-position: -96px -144px; -} -.icon-thumbs-down { - background-position: -120px -144px; -} -.icon-hand-right { - background-position: -144px -144px; -} -.icon-hand-left { - background-position: -168px -144px; -} -.icon-hand-up { - background-position: -192px -144px; -} -.icon-hand-down { - background-position: -216px -144px; -} -.icon-circle-arrow-right { - background-position: -240px -144px; -} -.icon-circle-arrow-left { - background-position: -264px -144px; -} -.icon-circle-arrow-up { - background-position: -288px -144px; -} -.icon-circle-arrow-down { - background-position: -312px -144px; -} -.icon-globe { - background-position: -336px -144px; -} -.icon-wrench { - background-position: -360px -144px; -} -.icon-tasks { - background-position: -384px -144px; -} -.icon-filter { - background-position: -408px -144px; -} -.icon-briefcase { - background-position: -432px -144px; -} -.icon-fullscreen { - background-position: -456px -144px; -} -.dropup, -.dropdown { - position: relative; -} -.dropdown-toggle { - *margin-bottom: -3px; -} -.dropdown-toggle:active, -.open .dropdown-toggle { - outline: 0; -} -.caret { - display: inline-block; - width: 0; - height: 0; - vertical-align: top; - border-top: 4px solid #000000; - border-right: 4px solid transparent; - border-left: 4px solid transparent; - content: ""; -} -.dropdown .caret { - margin-top: 8px; - margin-left: 2px; -} -.dropdown-menu { - position: absolute; - top: 100%; - left: 0; - z-index: 1000; - display: none; - float: left; - min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; - list-style: none; - background-color: #ffffff; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.2); - *border-right-width: 2px; - *border-bottom-width: 2px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -webkit-background-clip: padding-box; - -moz-background-clip: padding; - background-clip: padding-box; -} -.dropdown-menu.pull-right { - right: 0; - left: auto; -} -.dropdown-menu .divider { - *width: 100%; - height: 1px; - margin: 9px 1px; - *margin: -5px 0 5px; - overflow: hidden; - background-color: #e5e5e5; - border-bottom: 1px solid #ffffff; -} -.dropdown-menu > li > a { - display: block; - padding: 3px 20px; - clear: both; - font-weight: normal; - line-height: 20px; - color: #333333; - white-space: nowrap; -} -.dropdown-menu > li > a:hover, -.dropdown-menu > li > a:focus, -.dropdown-submenu:hover > a, -.dropdown-submenu:focus > a { - text-decoration: none; - color: #ffffff; - background-color: #0081c2; - background-image: -moz-linear-gradient(top, #0088cc, #0077b3); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); - background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); - background-image: -o-linear-gradient(top, #0088cc, #0077b3); - background-image: linear-gradient(to bottom, #0088cc, #0077b3); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); -} -.dropdown-menu > .active > a, -.dropdown-menu > .active > a:hover, -.dropdown-menu > .active > a:focus { - color: #ffffff; - text-decoration: none; - outline: 0; - background-color: #0081c2; - background-image: -moz-linear-gradient(top, #0088cc, #0077b3); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); - background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); - background-image: -o-linear-gradient(top, #0088cc, #0077b3); - background-image: linear-gradient(to bottom, #0088cc, #0077b3); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); -} -.dropdown-menu > .disabled > a, -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - color: #999999; -} -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - text-decoration: none; - background-color: transparent; - background-image: none; - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - cursor: default; -} -.open { - *z-index: 1000; -} -.open > .dropdown-menu { - display: block; -} -.dropdown-backdrop { - position: fixed; - left: 0; - right: 0; - bottom: 0; - top: 0; - z-index: 990; -} -.pull-right > .dropdown-menu { - right: 0; - left: auto; -} -.dropup .caret, -.navbar-fixed-bottom .dropdown .caret { - border-top: 0; - border-bottom: 4px solid #000000; - content: ""; -} -.dropup .dropdown-menu, -.navbar-fixed-bottom .dropdown .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: 1px; -} -.dropdown-submenu { - position: relative; -} -.dropdown-submenu > .dropdown-menu { - top: 0; - left: 100%; - margin-top: -6px; - margin-left: -1px; - -webkit-border-radius: 0 6px 6px 6px; - -moz-border-radius: 0 6px 6px 6px; - border-radius: 0 6px 6px 6px; -} -.dropdown-submenu:hover > .dropdown-menu { - display: block; -} -.dropup .dropdown-submenu > .dropdown-menu { - top: auto; - bottom: 0; - margin-top: 0; - margin-bottom: -2px; - -webkit-border-radius: 5px 5px 5px 0; - -moz-border-radius: 5px 5px 5px 0; - border-radius: 5px 5px 5px 0; -} -.dropdown-submenu > a:after { - display: block; - content: " "; - float: right; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; - border-width: 5px 0 5px 5px; - border-left-color: #cccccc; - margin-top: 5px; - margin-right: -10px; -} -.dropdown-submenu:hover > a:after { - border-left-color: #ffffff; -} -.dropdown-submenu.pull-left { - float: none; -} -.dropdown-submenu.pull-left > .dropdown-menu { - left: -100%; - margin-left: 10px; - -webkit-border-radius: 6px 0 6px 6px; - -moz-border-radius: 6px 0 6px 6px; - border-radius: 6px 0 6px 6px; -} -.dropdown .dropdown-menu .nav-header { - padding-left: 20px; - padding-right: 20px; -} -.typeahead { - z-index: 1051; - margin-top: 2px; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} -.well { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: #f5f5f5; - border: 1px solid #e3e3e3; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); -} -.well blockquote { - border-color: #ddd; - border-color: rgba(0, 0, 0, 0.15); -} -.well-large { - padding: 24px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} -.well-small { - padding: 9px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} -.fade { - opacity: 0; - -webkit-transition: opacity 0.15s linear; - -moz-transition: opacity 0.15s linear; - -o-transition: opacity 0.15s linear; - transition: opacity 0.15s linear; -} -.fade.in { - opacity: 1; -} -.collapse { - position: relative; - height: 0; - overflow: hidden; - -webkit-transition: height 0.35s ease; - -moz-transition: height 0.35s ease; - -o-transition: height 0.35s ease; - transition: height 0.35s ease; -} -.collapse.in { - height: auto; -} -.close { - float: right; - font-size: 20px; - font-weight: bold; - line-height: 20px; - color: #000000; - text-shadow: 0 1px 0 #ffffff; - opacity: 0.2; - filter: alpha(opacity=20); -} -.close:hover, -.close:focus { - color: #000000; - text-decoration: none; - cursor: pointer; - opacity: 0.4; - filter: alpha(opacity=40); -} -button.close { - padding: 0; - cursor: pointer; - background: transparent; - border: 0; - -webkit-appearance: none; -} -.btn { - display: inline-block; - *display: inline; - /* IE7 inline-block hack */ - *zoom: 1; - padding: 4px 12px; - margin-bottom: 0; - font-size: 14px; - line-height: 20px; - text-align: center; - vertical-align: middle; - cursor: pointer; - color: #333333; - text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); - background-color: #f5f5f5; - background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); - background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); - background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); - background-image: linear-gradient(to bottom, #ffffff, #e6e6e6); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); - border-color: #e6e6e6 #e6e6e6 #bfbfbf; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - *background-color: #e6e6e6; - /* Darken IE7 buttons by default so they stand out more given they won't have borders */ - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - border: 1px solid #cccccc; - *border: 0; - border-bottom-color: #b3b3b3; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - *margin-left: .3em; - -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); - -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); - box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); -} -.btn:hover, -.btn:focus, -.btn:active, -.btn.active, -.btn.disabled, -.btn[disabled] { - color: #333333; - background-color: #e6e6e6; - *background-color: #d9d9d9; -} -.btn:active, -.btn.active { - background-color: #cccccc \9; -} -.btn:first-child { - *margin-left: 0; -} -.btn:hover, -.btn:focus { - color: #333333; - text-decoration: none; - background-position: 0 -15px; - -webkit-transition: background-position 0.1s linear; - -moz-transition: background-position 0.1s linear; - -o-transition: background-position 0.1s linear; - transition: background-position 0.1s linear; -} -.btn:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -.btn.active, -.btn:active { - background-image: none; - outline: 0; - -webkit-box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); - -moz-box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); - box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); -} -.btn.disabled, -.btn[disabled] { - cursor: default; - background-image: none; - opacity: 0.65; - filter: alpha(opacity=65); - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} -.btn-large { - padding: 11px 19px; - font-size: 17.5px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} -.btn-large [class^="icon-"], -.btn-large [class*=" icon-"] { - margin-top: 4px; -} -.btn-small { - padding: 2px 10px; - font-size: 11.9px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} -.btn-small [class^="icon-"], -.btn-small [class*=" icon-"] { - margin-top: 0; -} -.btn-mini [class^="icon-"], -.btn-mini [class*=" icon-"] { - margin-top: -1px; -} -.btn-mini { - padding: 0 6px; - font-size: 10.5px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} -.btn-block { - display: block; - width: 100%; - padding-left: 0; - padding-right: 0; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -.btn-block + .btn-block { - margin-top: 5px; -} -input[type="submit"].btn-block, -input[type="reset"].btn-block, -input[type="button"].btn-block { - width: 100%; -} -.btn-primary.active, -.btn-warning.active, -.btn-danger.active, -.btn-success.active, -.btn-info.active, -.btn-inverse.active { - color: rgba(255, 255, 255, 0.75); -} -.btn-primary { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #006dcc; - background-image: -moz-linear-gradient(top, #0088cc, #0044cc); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); - background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); - background-image: -o-linear-gradient(top, #0088cc, #0044cc); - background-image: linear-gradient(to bottom, #0088cc, #0044cc); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0); - border-color: #0044cc #0044cc #002a80; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - *background-color: #0044cc; - /* Darken IE7 buttons by default so they stand out more given they won't have borders */ - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); -} -.btn-primary:hover, -.btn-primary:focus, -.btn-primary:active, -.btn-primary.active, -.btn-primary.disabled, -.btn-primary[disabled] { - color: #ffffff; - background-color: #0044cc; - *background-color: #003bb3; -} -.btn-primary:active, -.btn-primary.active { - background-color: #003399 \9; -} -.btn-warning { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #faa732; - background-image: -moz-linear-gradient(top, #fbb450, #f89406); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); - background-image: -webkit-linear-gradient(top, #fbb450, #f89406); - background-image: -o-linear-gradient(top, #fbb450, #f89406); - background-image: linear-gradient(to bottom, #fbb450, #f89406); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); - border-color: #f89406 #f89406 #ad6704; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - *background-color: #f89406; - /* Darken IE7 buttons by default so they stand out more given they won't have borders */ - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); -} -.btn-warning:hover, -.btn-warning:focus, -.btn-warning:active, -.btn-warning.active, -.btn-warning.disabled, -.btn-warning[disabled] { - color: #ffffff; - background-color: #f89406; - *background-color: #df8505; -} -.btn-warning:active, -.btn-warning.active { - background-color: #c67605 \9; -} -.btn-danger { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #da4f49; - background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f)); - background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f); - background-image: -o-linear-gradient(top, #ee5f5b, #bd362f); - background-image: linear-gradient(to bottom, #ee5f5b, #bd362f); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0); - border-color: #bd362f #bd362f #802420; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - *background-color: #bd362f; - /* Darken IE7 buttons by default so they stand out more given they won't have borders */ - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); -} -.btn-danger:hover, -.btn-danger:focus, -.btn-danger:active, -.btn-danger.active, -.btn-danger.disabled, -.btn-danger[disabled] { - color: #ffffff; - background-color: #bd362f; - *background-color: #a9302a; -} -.btn-danger:active, -.btn-danger.active { - background-color: #942a25 \9; -} -.btn-success { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #5bb75b; - background-image: -moz-linear-gradient(top, #62c462, #51a351); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351)); - background-image: -webkit-linear-gradient(top, #62c462, #51a351); - background-image: -o-linear-gradient(top, #62c462, #51a351); - background-image: linear-gradient(to bottom, #62c462, #51a351); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0); - border-color: #51a351 #51a351 #387038; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - *background-color: #51a351; - /* Darken IE7 buttons by default so they stand out more given they won't have borders */ - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); -} -.btn-success:hover, -.btn-success:focus, -.btn-success:active, -.btn-success.active, -.btn-success.disabled, -.btn-success[disabled] { - color: #ffffff; - background-color: #51a351; - *background-color: #499249; -} -.btn-success:active, -.btn-success.active { - background-color: #408140 \9; -} -.btn-info { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #49afcd; - background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4)); - background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4); - background-image: -o-linear-gradient(top, #5bc0de, #2f96b4); - background-image: linear-gradient(to bottom, #5bc0de, #2f96b4); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0); - border-color: #2f96b4 #2f96b4 #1f6377; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - *background-color: #2f96b4; - /* Darken IE7 buttons by default so they stand out more given they won't have borders */ - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); -} -.btn-info:hover, -.btn-info:focus, -.btn-info:active, -.btn-info.active, -.btn-info.disabled, -.btn-info[disabled] { - color: #ffffff; - background-color: #2f96b4; - *background-color: #2a85a0; -} -.btn-info:active, -.btn-info.active { - background-color: #24748c \9; -} -.btn-inverse { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #363636; - background-image: -moz-linear-gradient(top, #444444, #222222); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222)); - background-image: -webkit-linear-gradient(top, #444444, #222222); - background-image: -o-linear-gradient(top, #444444, #222222); - background-image: linear-gradient(to bottom, #444444, #222222); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0); - border-color: #222222 #222222 #000000; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - *background-color: #222222; - /* Darken IE7 buttons by default so they stand out more given they won't have borders */ - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); -} -.btn-inverse:hover, -.btn-inverse:focus, -.btn-inverse:active, -.btn-inverse.active, -.btn-inverse.disabled, -.btn-inverse[disabled] { - color: #ffffff; - background-color: #222222; - *background-color: #151515; -} -.btn-inverse:active, -.btn-inverse.active { - background-color: #080808 \9; -} -button.btn, -input[type="submit"].btn { - *padding-top: 3px; - *padding-bottom: 3px; -} -button.btn::-moz-focus-inner, -input[type="submit"].btn::-moz-focus-inner { - padding: 0; - border: 0; -} -button.btn.btn-large, -input[type="submit"].btn.btn-large { - *padding-top: 7px; - *padding-bottom: 7px; -} -button.btn.btn-small, -input[type="submit"].btn.btn-small { - *padding-top: 3px; - *padding-bottom: 3px; -} -button.btn.btn-mini, -input[type="submit"].btn.btn-mini { - *padding-top: 1px; - *padding-bottom: 1px; -} -.btn-link, -.btn-link:active, -.btn-link[disabled] { - background-color: transparent; - background-image: none; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} -.btn-link { - border-color: transparent; - cursor: pointer; - color: #0088cc; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} -.btn-link:hover, -.btn-link:focus { - color: #005580; - text-decoration: underline; - background-color: transparent; -} -.btn-link[disabled]:hover, -.btn-link[disabled]:focus { - color: #333333; - text-decoration: none; -} -.btn-group { - position: relative; - display: inline-block; - *display: inline; - /* IE7 inline-block hack */ - *zoom: 1; - font-size: 0; - vertical-align: middle; - white-space: nowrap; - *margin-left: .3em; -} -.btn-group:first-child { - *margin-left: 0; -} -.btn-group + .btn-group { - margin-left: 5px; -} -.btn-toolbar { - font-size: 0; - margin-top: 10px; - margin-bottom: 10px; -} -.btn-toolbar > .btn + .btn, -.btn-toolbar > .btn-group + .btn, -.btn-toolbar > .btn + .btn-group { - margin-left: 5px; -} -.btn-group > .btn { - position: relative; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} -.btn-group > .btn + .btn { - margin-left: -1px; -} -.btn-group > .btn, -.btn-group > .dropdown-menu, -.btn-group > .popover { - font-size: 14px; -} -.btn-group > .btn-mini { - font-size: 10.5px; -} -.btn-group > .btn-small { - font-size: 11.9px; -} -.btn-group > .btn-large { - font-size: 17.5px; -} -.btn-group > .btn:first-child { - margin-left: 0; - -webkit-border-top-left-radius: 4px; - -moz-border-radius-topleft: 4px; - border-top-left-radius: 4px; - -webkit-border-bottom-left-radius: 4px; - -moz-border-radius-bottomleft: 4px; - border-bottom-left-radius: 4px; -} -.btn-group > .btn:last-child, -.btn-group > .dropdown-toggle { - -webkit-border-top-right-radius: 4px; - -moz-border-radius-topright: 4px; - border-top-right-radius: 4px; - -webkit-border-bottom-right-radius: 4px; - -moz-border-radius-bottomright: 4px; - border-bottom-right-radius: 4px; -} -.btn-group > .btn.large:first-child { - margin-left: 0; - -webkit-border-top-left-radius: 6px; - -moz-border-radius-topleft: 6px; - border-top-left-radius: 6px; - -webkit-border-bottom-left-radius: 6px; - -moz-border-radius-bottomleft: 6px; - border-bottom-left-radius: 6px; -} -.btn-group > .btn.large:last-child, -.btn-group > .large.dropdown-toggle { - -webkit-border-top-right-radius: 6px; - -moz-border-radius-topright: 6px; - border-top-right-radius: 6px; - -webkit-border-bottom-right-radius: 6px; - -moz-border-radius-bottomright: 6px; - border-bottom-right-radius: 6px; -} -.btn-group > .btn:hover, -.btn-group > .btn:focus, -.btn-group > .btn:active, -.btn-group > .btn.active { - z-index: 2; -} -.btn-group .dropdown-toggle:active, -.btn-group.open .dropdown-toggle { - outline: 0; -} -.btn-group > .btn + .dropdown-toggle { - padding-left: 8px; - padding-right: 8px; - -webkit-box-shadow: inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); - -moz-box-shadow: inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); - box-shadow: inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); - *padding-top: 5px; - *padding-bottom: 5px; -} -.btn-group > .btn-mini + .dropdown-toggle { - padding-left: 5px; - padding-right: 5px; - *padding-top: 2px; - *padding-bottom: 2px; -} -.btn-group > .btn-small + .dropdown-toggle { - *padding-top: 5px; - *padding-bottom: 4px; -} -.btn-group > .btn-large + .dropdown-toggle { - padding-left: 12px; - padding-right: 12px; - *padding-top: 7px; - *padding-bottom: 7px; -} -.btn-group.open .dropdown-toggle { - background-image: none; - -webkit-box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); - -moz-box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); - box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); -} -.btn-group.open .btn.dropdown-toggle { - background-color: #e6e6e6; -} -.btn-group.open .btn-primary.dropdown-toggle { - background-color: #0044cc; -} -.btn-group.open .btn-warning.dropdown-toggle { - background-color: #f89406; -} -.btn-group.open .btn-danger.dropdown-toggle { - background-color: #bd362f; -} -.btn-group.open .btn-success.dropdown-toggle { - background-color: #51a351; -} -.btn-group.open .btn-info.dropdown-toggle { - background-color: #2f96b4; -} -.btn-group.open .btn-inverse.dropdown-toggle { - background-color: #222222; -} -.btn .caret { - margin-top: 8px; - margin-left: 0; -} -.btn-large .caret { - margin-top: 6px; -} -.btn-large .caret { - border-left-width: 5px; - border-right-width: 5px; - border-top-width: 5px; -} -.btn-mini .caret, -.btn-small .caret { - margin-top: 8px; -} -.dropup .btn-large .caret { - border-bottom-width: 5px; -} -.btn-primary .caret, -.btn-warning .caret, -.btn-danger .caret, -.btn-info .caret, -.btn-success .caret, -.btn-inverse .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; -} -.btn-group-vertical { - display: inline-block; - *display: inline; - /* IE7 inline-block hack */ - *zoom: 1; -} -.btn-group-vertical > .btn { - display: block; - float: none; - max-width: 100%; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} -.btn-group-vertical > .btn + .btn { - margin-left: 0; - margin-top: -1px; -} -.btn-group-vertical > .btn:first-child { - -webkit-border-radius: 4px 4px 0 0; - -moz-border-radius: 4px 4px 0 0; - border-radius: 4px 4px 0 0; -} -.btn-group-vertical > .btn:last-child { - -webkit-border-radius: 0 0 4px 4px; - -moz-border-radius: 0 0 4px 4px; - border-radius: 0 0 4px 4px; -} -.btn-group-vertical > .btn-large:first-child { - -webkit-border-radius: 6px 6px 0 0; - -moz-border-radius: 6px 6px 0 0; - border-radius: 6px 6px 0 0; -} -.btn-group-vertical > .btn-large:last-child { - -webkit-border-radius: 0 0 6px 6px; - -moz-border-radius: 0 0 6px 6px; - border-radius: 0 0 6px 6px; -} -.alert { - padding: 8px 35px 8px 14px; - margin-bottom: 20px; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); - background-color: #fcf8e3; - border: 1px solid #fbeed5; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} -.alert, -.alert h4 { - color: #c09853; -} -.alert h4 { - margin: 0; -} -.alert .close { - position: relative; - top: -2px; - right: -21px; - line-height: 20px; -} -.alert-success { - background-color: #dff0d8; - border-color: #d6e9c6; - color: #468847; -} -.alert-success h4 { - color: #468847; -} -.alert-danger, -.alert-error { - background-color: #f2dede; - border-color: #eed3d7; - color: #b94a48; -} -.alert-danger h4, -.alert-error h4 { - color: #b94a48; -} -.alert-info { - background-color: #d9edf7; - border-color: #bce8f1; - color: #3a87ad; -} -.alert-info h4 { - color: #3a87ad; -} -.alert-block { - padding-top: 14px; - padding-bottom: 14px; -} -.alert-block > p, -.alert-block > ul { - margin-bottom: 0; -} -.alert-block p + p { - margin-top: 5px; -} -.nav { - margin-left: 0; - margin-bottom: 20px; - list-style: none; -} -.nav > li > a { - display: block; -} -.nav > li > a:hover, -.nav > li > a:focus { - text-decoration: none; - background-color: #eeeeee; -} -.nav > li > a > img { - max-width: none; -} -.nav > .pull-right { - float: right; -} -.nav-header { - display: block; - padding: 3px 15px; - font-size: 11px; - font-weight: bold; - line-height: 20px; - color: #999999; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); - text-transform: uppercase; -} -.nav li + .nav-header { - margin-top: 9px; -} -.nav-list { - padding-left: 15px; - padding-right: 15px; - margin-bottom: 0; -} -.nav-list > li > a, -.nav-list .nav-header { - margin-left: -15px; - margin-right: -15px; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); -} -.nav-list > li > a { - padding: 3px 15px; -} -.nav-list > .active > a, -.nav-list > .active > a:hover, -.nav-list > .active > a:focus { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); - background-color: #0088cc; -} -.nav-list [class^="icon-"], -.nav-list [class*=" icon-"] { - margin-right: 2px; -} -.nav-list .divider { - *width: 100%; - height: 1px; - margin: 9px 1px; - *margin: -5px 0 5px; - overflow: hidden; - background-color: #e5e5e5; - border-bottom: 1px solid #ffffff; -} -.nav-tabs, -.nav-pills { - *zoom: 1; -} -.nav-tabs:before, -.nav-pills:before, -.nav-tabs:after, -.nav-pills:after { - display: table; - content: ""; - line-height: 0; -} -.nav-tabs:after, -.nav-pills:after { - clear: both; -} -.nav-tabs > li, -.nav-pills > li { - float: left; -} -.nav-tabs > li > a, -.nav-pills > li > a { - padding-right: 12px; - padding-left: 12px; - margin-right: 2px; - line-height: 14px; -} -.nav-tabs { - border-bottom: 1px solid #ddd; -} -.nav-tabs > li { - margin-bottom: -1px; -} -.nav-tabs > li > a { - padding-top: 8px; - padding-bottom: 8px; - line-height: 20px; - border: 1px solid transparent; - -webkit-border-radius: 4px 4px 0 0; - -moz-border-radius: 4px 4px 0 0; - border-radius: 4px 4px 0 0; -} -.nav-tabs > li > a:hover, -.nav-tabs > li > a:focus { - border-color: #eeeeee #eeeeee #dddddd; -} -.nav-tabs > .active > a, -.nav-tabs > .active > a:hover, -.nav-tabs > .active > a:focus { - color: #555555; - background-color: #ffffff; - border: 1px solid #ddd; - border-bottom-color: transparent; - cursor: default; -} -.nav-pills > li > a { - padding-top: 8px; - padding-bottom: 8px; - margin-top: 2px; - margin-bottom: 2px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; -} -.nav-pills > .active > a, -.nav-pills > .active > a:hover, -.nav-pills > .active > a:focus { - color: #ffffff; - background-color: #0088cc; -} -.nav-stacked > li { - float: none; -} -.nav-stacked > li > a { - margin-right: 0; -} -.nav-tabs.nav-stacked { - border-bottom: 0; -} -.nav-tabs.nav-stacked > li > a { - border: 1px solid #ddd; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} -.nav-tabs.nav-stacked > li:first-child > a { - -webkit-border-top-right-radius: 4px; - -moz-border-radius-topright: 4px; - border-top-right-radius: 4px; - -webkit-border-top-left-radius: 4px; - -moz-border-radius-topleft: 4px; - border-top-left-radius: 4px; -} -.nav-tabs.nav-stacked > li:last-child > a { - -webkit-border-bottom-right-radius: 4px; - -moz-border-radius-bottomright: 4px; - border-bottom-right-radius: 4px; - -webkit-border-bottom-left-radius: 4px; - -moz-border-radius-bottomleft: 4px; - border-bottom-left-radius: 4px; -} -.nav-tabs.nav-stacked > li > a:hover, -.nav-tabs.nav-stacked > li > a:focus { - border-color: #ddd; - z-index: 2; -} -.nav-pills.nav-stacked > li > a { - margin-bottom: 3px; -} -.nav-pills.nav-stacked > li:last-child > a { - margin-bottom: 1px; -} -.nav-tabs .dropdown-menu { - -webkit-border-radius: 0 0 6px 6px; - -moz-border-radius: 0 0 6px 6px; - border-radius: 0 0 6px 6px; -} -.nav-pills .dropdown-menu { - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} -.nav .dropdown-toggle .caret { - border-top-color: #0088cc; - border-bottom-color: #0088cc; - margin-top: 6px; -} -.nav .dropdown-toggle:hover .caret, -.nav .dropdown-toggle:focus .caret { - border-top-color: #005580; - border-bottom-color: #005580; -} -/* move down carets for tabs */ -.nav-tabs .dropdown-toggle .caret { - margin-top: 8px; -} -.nav .active .dropdown-toggle .caret { - border-top-color: #fff; - border-bottom-color: #fff; -} -.nav-tabs .active .dropdown-toggle .caret { - border-top-color: #555555; - border-bottom-color: #555555; -} -.nav > .dropdown.active > a:hover, -.nav > .dropdown.active > a:focus { - cursor: pointer; -} -.nav-tabs .open .dropdown-toggle, -.nav-pills .open .dropdown-toggle, -.nav > li.dropdown.open.active > a:hover, -.nav > li.dropdown.open.active > a:focus { - color: #ffffff; - background-color: #999999; - border-color: #999999; -} -.nav li.dropdown.open .caret, -.nav li.dropdown.open.active .caret, -.nav li.dropdown.open a:hover .caret, -.nav li.dropdown.open a:focus .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; - opacity: 1; - filter: alpha(opacity=100); -} -.tabs-stacked .open > a:hover, -.tabs-stacked .open > a:focus { - border-color: #999999; -} -.tabbable { - *zoom: 1; -} -.tabbable:before, -.tabbable:after { - display: table; - content: ""; - line-height: 0; -} -.tabbable:after { - clear: both; -} -.tab-content { - overflow: auto; -} -.tabs-below > .nav-tabs, -.tabs-right > .nav-tabs, -.tabs-left > .nav-tabs { - border-bottom: 0; -} -.tab-content > .tab-pane, -.pill-content > .pill-pane { - display: none; -} -.tab-content > .active, -.pill-content > .active { - display: block; -} -.tabs-below > .nav-tabs { - border-top: 1px solid #ddd; -} -.tabs-below > .nav-tabs > li { - margin-top: -1px; - margin-bottom: 0; -} -.tabs-below > .nav-tabs > li > a { - -webkit-border-radius: 0 0 4px 4px; - -moz-border-radius: 0 0 4px 4px; - border-radius: 0 0 4px 4px; -} -.tabs-below > .nav-tabs > li > a:hover, -.tabs-below > .nav-tabs > li > a:focus { - border-bottom-color: transparent; - border-top-color: #ddd; -} -.tabs-below > .nav-tabs > .active > a, -.tabs-below > .nav-tabs > .active > a:hover, -.tabs-below > .nav-tabs > .active > a:focus { - border-color: transparent #ddd #ddd #ddd; -} -.tabs-left > .nav-tabs > li, -.tabs-right > .nav-tabs > li { - float: none; -} -.tabs-left > .nav-tabs > li > a, -.tabs-right > .nav-tabs > li > a { - min-width: 74px; - margin-right: 0; - margin-bottom: 3px; -} -.tabs-left > .nav-tabs { - float: left; - margin-right: 19px; - border-right: 1px solid #ddd; -} -.tabs-left > .nav-tabs > li > a { - margin-right: -1px; - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; -} -.tabs-left > .nav-tabs > li > a:hover, -.tabs-left > .nav-tabs > li > a:focus { - border-color: #eeeeee #dddddd #eeeeee #eeeeee; -} -.tabs-left > .nav-tabs .active > a, -.tabs-left > .nav-tabs .active > a:hover, -.tabs-left > .nav-tabs .active > a:focus { - border-color: #ddd transparent #ddd #ddd; - *border-right-color: #ffffff; -} -.tabs-right > .nav-tabs { - float: right; - margin-left: 19px; - border-left: 1px solid #ddd; -} -.tabs-right > .nav-tabs > li > a { - margin-left: -1px; - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} -.tabs-right > .nav-tabs > li > a:hover, -.tabs-right > .nav-tabs > li > a:focus { - border-color: #eeeeee #eeeeee #eeeeee #dddddd; -} -.tabs-right > .nav-tabs .active > a, -.tabs-right > .nav-tabs .active > a:hover, -.tabs-right > .nav-tabs .active > a:focus { - border-color: #ddd #ddd #ddd transparent; - *border-left-color: #ffffff; -} -.nav > .disabled > a { - color: #999999; -} -.nav > .disabled > a:hover, -.nav > .disabled > a:focus { - text-decoration: none; - background-color: transparent; - cursor: default; -} -.navbar { - overflow: visible; - margin-bottom: 20px; - *position: relative; - *z-index: 2; -} -.navbar-inner { - min-height: 40px; - padding-left: 20px; - padding-right: 20px; - background-color: #fafafa; - background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2)); - background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2); - background-image: -o-linear-gradient(top, #ffffff, #f2f2f2); - background-image: linear-gradient(to bottom, #ffffff, #f2f2f2); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0); - border: 1px solid #d4d4d4; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); - -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); - box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); - *zoom: 1; -} -.navbar-inner:before, -.navbar-inner:after { - display: table; - content: ""; - line-height: 0; -} -.navbar-inner:after { - clear: both; -} -.navbar .container { - width: auto; -} -.nav-collapse.collapse { - height: auto; - overflow: visible; -} -.navbar .brand { - float: left; - display: block; - padding: 10px 20px 10px; - margin-left: -20px; - font-size: 20px; - font-weight: 200; - color: #777777; - text-shadow: 0 1px 0 #ffffff; -} -.navbar .brand:hover, -.navbar .brand:focus { - text-decoration: none; -} -.navbar-text { - margin-bottom: 0; - line-height: 40px; - color: #777777; -} -.navbar-link { - color: #777777; -} -.navbar-link:hover, -.navbar-link:focus { - color: #333333; -} -.navbar .divider-vertical { - height: 40px; - margin: 0 9px; - border-left: 1px solid #f2f2f2; - border-right: 1px solid #ffffff; -} -.navbar .btn, -.navbar .btn-group { - margin-top: 5px; -} -.navbar .btn-group .btn, -.navbar .input-prepend .btn, -.navbar .input-append .btn, -.navbar .input-prepend .btn-group, -.navbar .input-append .btn-group { - margin-top: 0; -} -.navbar-form { - margin-bottom: 0; - *zoom: 1; -} -.navbar-form:before, -.navbar-form:after { - display: table; - content: ""; - line-height: 0; -} -.navbar-form:after { - clear: both; -} -.navbar-form input, -.navbar-form select, -.navbar-form .radio, -.navbar-form .checkbox { - margin-top: 5px; -} -.navbar-form input, -.navbar-form select, -.navbar-form .btn { - display: inline-block; - margin-bottom: 0; -} -.navbar-form input[type="image"], -.navbar-form input[type="checkbox"], -.navbar-form input[type="radio"] { - margin-top: 3px; -} -.navbar-form .input-append, -.navbar-form .input-prepend { - margin-top: 5px; - white-space: nowrap; -} -.navbar-form .input-append input, -.navbar-form .input-prepend input { - margin-top: 0; -} -.navbar-search { - position: relative; - float: left; - margin-top: 5px; - margin-bottom: 0; -} -.navbar-search .search-query { - margin-bottom: 0; - padding: 4px 14px; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 13px; - font-weight: normal; - line-height: 1; - -webkit-border-radius: 15px; - -moz-border-radius: 15px; - border-radius: 15px; -} -.navbar-static-top { - position: static; - margin-bottom: 0; -} -.navbar-static-top .navbar-inner { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} -.navbar-fixed-top, -.navbar-fixed-bottom { - position: fixed; - right: 0; - left: 0; - z-index: 1030; - margin-bottom: 0; -} -.navbar-fixed-top .navbar-inner, -.navbar-static-top .navbar-inner { - border-width: 0 0 1px; -} -.navbar-fixed-bottom .navbar-inner { - border-width: 1px 0 0; -} -.navbar-fixed-top .navbar-inner, -.navbar-fixed-bottom .navbar-inner { - padding-left: 0; - padding-right: 0; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} -.navbar-static-top .container, -.navbar-fixed-top .container, -.navbar-fixed-bottom .container { - width: 940px; -} -.navbar-fixed-top { - top: 0; -} -.navbar-fixed-top .navbar-inner, -.navbar-static-top .navbar-inner { - -webkit-box-shadow: 0 1px 10px rgba(0,0,0,.1); - -moz-box-shadow: 0 1px 10px rgba(0,0,0,.1); - box-shadow: 0 1px 10px rgba(0,0,0,.1); -} -.navbar-fixed-bottom { - bottom: 0; -} -.navbar-fixed-bottom .navbar-inner { - -webkit-box-shadow: 0 -1px 10px rgba(0,0,0,.1); - -moz-box-shadow: 0 -1px 10px rgba(0,0,0,.1); - box-shadow: 0 -1px 10px rgba(0,0,0,.1); -} -.navbar .nav { - position: relative; - left: 0; - display: block; - float: left; - margin: 0 10px 0 0; -} -.navbar .nav.pull-right { - float: right; - margin-right: 0; -} -.navbar .nav > li { - float: left; -} -.navbar .nav > li > a { - float: none; - padding: 10px 15px 10px; - color: #777777; - text-decoration: none; - text-shadow: 0 1px 0 #ffffff; -} -.navbar .nav .dropdown-toggle .caret { - margin-top: 8px; -} -.navbar .nav > li > a:focus, -.navbar .nav > li > a:hover { - background-color: transparent; - color: #333333; - text-decoration: none; -} -.navbar .nav > .active > a, -.navbar .nav > .active > a:hover, -.navbar .nav > .active > a:focus { - color: #555555; - text-decoration: none; - background-color: #e5e5e5; - -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); - -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); - box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); -} -.navbar .btn-navbar { - display: none; - float: right; - padding: 7px 10px; - margin-left: 5px; - margin-right: 5px; - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #ededed; - background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5)); - background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5); - background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5); - background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0); - border-color: #e5e5e5 #e5e5e5 #bfbfbf; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - *background-color: #e5e5e5; - /* Darken IE7 buttons by default so they stand out more given they won't have borders */ - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075); - -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075); - box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075); -} -.navbar .btn-navbar:hover, -.navbar .btn-navbar:focus, -.navbar .btn-navbar:active, -.navbar .btn-navbar.active, -.navbar .btn-navbar.disabled, -.navbar .btn-navbar[disabled] { - color: #ffffff; - background-color: #e5e5e5; - *background-color: #d9d9d9; -} -.navbar .btn-navbar:active, -.navbar .btn-navbar.active { - background-color: #cccccc \9; -} -.navbar .btn-navbar .icon-bar { - display: block; - width: 18px; - height: 2px; - background-color: #f5f5f5; - -webkit-border-radius: 1px; - -moz-border-radius: 1px; - border-radius: 1px; - -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); - -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); -} -.btn-navbar .icon-bar + .icon-bar { - margin-top: 3px; -} -.navbar .nav > li > .dropdown-menu:before { - content: ''; - display: inline-block; - border-left: 7px solid transparent; - border-right: 7px solid transparent; - border-bottom: 7px solid #ccc; - border-bottom-color: rgba(0, 0, 0, 0.2); - position: absolute; - top: -7px; - left: 9px; -} -.navbar .nav > li > .dropdown-menu:after { - content: ''; - display: inline-block; - border-left: 6px solid transparent; - border-right: 6px solid transparent; - border-bottom: 6px solid #ffffff; - position: absolute; - top: -6px; - left: 10px; -} -.navbar-fixed-bottom .nav > li > .dropdown-menu:before { - border-top: 7px solid #ccc; - border-top-color: rgba(0, 0, 0, 0.2); - border-bottom: 0; - bottom: -7px; - top: auto; -} -.navbar-fixed-bottom .nav > li > .dropdown-menu:after { - border-top: 6px solid #ffffff; - border-bottom: 0; - bottom: -6px; - top: auto; -} -.navbar .nav li.dropdown > a:hover .caret, -.navbar .nav li.dropdown > a:focus .caret { - border-top-color: #333333; - border-bottom-color: #333333; -} -.navbar .nav li.dropdown.open > .dropdown-toggle, -.navbar .nav li.dropdown.active > .dropdown-toggle, -.navbar .nav li.dropdown.open.active > .dropdown-toggle { - background-color: #e5e5e5; - color: #555555; -} -.navbar .nav li.dropdown > .dropdown-toggle .caret { - border-top-color: #777777; - border-bottom-color: #777777; -} -.navbar .nav li.dropdown.open > .dropdown-toggle .caret, -.navbar .nav li.dropdown.active > .dropdown-toggle .caret, -.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret { - border-top-color: #555555; - border-bottom-color: #555555; -} -.navbar .pull-right > li > .dropdown-menu, -.navbar .nav > li > .dropdown-menu.pull-right { - left: auto; - right: 0; -} -.navbar .pull-right > li > .dropdown-menu:before, -.navbar .nav > li > .dropdown-menu.pull-right:before { - left: auto; - right: 12px; -} -.navbar .pull-right > li > .dropdown-menu:after, -.navbar .nav > li > .dropdown-menu.pull-right:after { - left: auto; - right: 13px; -} -.navbar .pull-right > li > .dropdown-menu .dropdown-menu, -.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu { - left: auto; - right: 100%; - margin-left: 0; - margin-right: -1px; - -webkit-border-radius: 6px 0 6px 6px; - -moz-border-radius: 6px 0 6px 6px; - border-radius: 6px 0 6px 6px; -} -.navbar-inverse .navbar-inner { - background-color: #1b1b1b; - background-image: -moz-linear-gradient(top, #222222, #111111); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111)); - background-image: -webkit-linear-gradient(top, #222222, #111111); - background-image: -o-linear-gradient(top, #222222, #111111); - background-image: linear-gradient(to bottom, #222222, #111111); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0); - border-color: #252525; -} -.navbar-inverse .brand, -.navbar-inverse .nav > li > a { - color: #999999; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); -} -.navbar-inverse .brand:hover, -.navbar-inverse .nav > li > a:hover, -.navbar-inverse .brand:focus, -.navbar-inverse .nav > li > a:focus { - color: #ffffff; -} -.navbar-inverse .brand { - color: #999999; -} -.navbar-inverse .navbar-text { - color: #999999; -} -.navbar-inverse .nav > li > a:focus, -.navbar-inverse .nav > li > a:hover { - background-color: transparent; - color: #ffffff; -} -.navbar-inverse .nav .active > a, -.navbar-inverse .nav .active > a:hover, -.navbar-inverse .nav .active > a:focus { - color: #ffffff; - background-color: #111111; -} -.navbar-inverse .navbar-link { - color: #999999; -} -.navbar-inverse .navbar-link:hover, -.navbar-inverse .navbar-link:focus { - color: #ffffff; -} -.navbar-inverse .divider-vertical { - border-left-color: #111111; - border-right-color: #222222; -} -.navbar-inverse .nav li.dropdown.open > .dropdown-toggle, -.navbar-inverse .nav li.dropdown.active > .dropdown-toggle, -.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle { - background-color: #111111; - color: #ffffff; -} -.navbar-inverse .nav li.dropdown > a:hover .caret, -.navbar-inverse .nav li.dropdown > a:focus .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; -} -.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret { - border-top-color: #999999; - border-bottom-color: #999999; -} -.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret, -.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret, -.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; -} -.navbar-inverse .navbar-search .search-query { - color: #ffffff; - background-color: #515151; - border-color: #111111; - -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15); - -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15); - box-shadow: inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15); - -webkit-transition: none; - -moz-transition: none; - -o-transition: none; - transition: none; -} -.navbar-inverse .navbar-search .search-query:-moz-placeholder { - color: #cccccc; -} -.navbar-inverse .navbar-search .search-query:-ms-input-placeholder { - color: #cccccc; -} -.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder { - color: #cccccc; -} -.navbar-inverse .navbar-search .search-query:focus, -.navbar-inverse .navbar-search .search-query.focused { - padding: 5px 15px; - color: #333333; - text-shadow: 0 1px 0 #ffffff; - background-color: #ffffff; - border: 0; - -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); - -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); - box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); - outline: 0; -} -.navbar-inverse .btn-navbar { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #0e0e0e; - background-image: -moz-linear-gradient(top, #151515, #040404); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404)); - background-image: -webkit-linear-gradient(top, #151515, #040404); - background-image: -o-linear-gradient(top, #151515, #040404); - background-image: linear-gradient(to bottom, #151515, #040404); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0); - border-color: #040404 #040404 #000000; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - *background-color: #040404; - /* Darken IE7 buttons by default so they stand out more given they won't have borders */ - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); -} -.navbar-inverse .btn-navbar:hover, -.navbar-inverse .btn-navbar:focus, -.navbar-inverse .btn-navbar:active, -.navbar-inverse .btn-navbar.active, -.navbar-inverse .btn-navbar.disabled, -.navbar-inverse .btn-navbar[disabled] { - color: #ffffff; - background-color: #040404; - *background-color: #000000; -} -.navbar-inverse .btn-navbar:active, -.navbar-inverse .btn-navbar.active { - background-color: #000000 \9; -} -.breadcrumb { - padding: 8px 15px; - margin: 0 0 20px; - list-style: none; - background-color: #f5f5f5; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} -.breadcrumb > li { - display: inline-block; - *display: inline; - /* IE7 inline-block hack */ - *zoom: 1; - text-shadow: 0 1px 0 #ffffff; -} -.breadcrumb > li > .divider { - padding: 0 5px; - color: #ccc; -} -.breadcrumb > .active { - color: #999999; -} -.pagination { - margin: 20px 0; -} -.pagination ul { - display: inline-block; - *display: inline; - /* IE7 inline-block hack */ - *zoom: 1; - margin-left: 0; - margin-bottom: 0; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); -} -.pagination ul > li { - display: inline; -} -.pagination ul > li > a, -.pagination ul > li > span { - float: left; - padding: 4px 12px; - line-height: 20px; - text-decoration: none; - background-color: #ffffff; - border: 1px solid #dddddd; - border-left-width: 0; -} -.pagination ul > li > a:hover, -.pagination ul > li > a:focus, -.pagination ul > .active > a, -.pagination ul > .active > span { - background-color: #f5f5f5; -} -.pagination ul > .active > a, -.pagination ul > .active > span { - color: #999999; - cursor: default; -} -.pagination ul > .disabled > span, -.pagination ul > .disabled > a, -.pagination ul > .disabled > a:hover, -.pagination ul > .disabled > a:focus { - color: #999999; - background-color: transparent; - cursor: default; -} -.pagination ul > li:first-child > a, -.pagination ul > li:first-child > span { - border-left-width: 1px; - -webkit-border-top-left-radius: 4px; - -moz-border-radius-topleft: 4px; - border-top-left-radius: 4px; - -webkit-border-bottom-left-radius: 4px; - -moz-border-radius-bottomleft: 4px; - border-bottom-left-radius: 4px; -} -.pagination ul > li:last-child > a, -.pagination ul > li:last-child > span { - -webkit-border-top-right-radius: 4px; - -moz-border-radius-topright: 4px; - border-top-right-radius: 4px; - -webkit-border-bottom-right-radius: 4px; - -moz-border-radius-bottomright: 4px; - border-bottom-right-radius: 4px; -} -.pagination-centered { - text-align: center; -} -.pagination-right { - text-align: right; -} -.pagination-large ul > li > a, -.pagination-large ul > li > span { - padding: 11px 19px; - font-size: 17.5px; -} -.pagination-large ul > li:first-child > a, -.pagination-large ul > li:first-child > span { - -webkit-border-top-left-radius: 6px; - -moz-border-radius-topleft: 6px; - border-top-left-radius: 6px; - -webkit-border-bottom-left-radius: 6px; - -moz-border-radius-bottomleft: 6px; - border-bottom-left-radius: 6px; -} -.pagination-large ul > li:last-child > a, -.pagination-large ul > li:last-child > span { - -webkit-border-top-right-radius: 6px; - -moz-border-radius-topright: 6px; - border-top-right-radius: 6px; - -webkit-border-bottom-right-radius: 6px; - -moz-border-radius-bottomright: 6px; - border-bottom-right-radius: 6px; -} -.pagination-mini ul > li:first-child > a, -.pagination-small ul > li:first-child > a, -.pagination-mini ul > li:first-child > span, -.pagination-small ul > li:first-child > span { - -webkit-border-top-left-radius: 3px; - -moz-border-radius-topleft: 3px; - border-top-left-radius: 3px; - -webkit-border-bottom-left-radius: 3px; - -moz-border-radius-bottomleft: 3px; - border-bottom-left-radius: 3px; -} -.pagination-mini ul > li:last-child > a, -.pagination-small ul > li:last-child > a, -.pagination-mini ul > li:last-child > span, -.pagination-small ul > li:last-child > span { - -webkit-border-top-right-radius: 3px; - -moz-border-radius-topright: 3px; - border-top-right-radius: 3px; - -webkit-border-bottom-right-radius: 3px; - -moz-border-radius-bottomright: 3px; - border-bottom-right-radius: 3px; -} -.pagination-small ul > li > a, -.pagination-small ul > li > span { - padding: 2px 10px; - font-size: 11.9px; -} -.pagination-mini ul > li > a, -.pagination-mini ul > li > span { - padding: 0 6px; - font-size: 10.5px; -} -.pager { - margin: 20px 0; - list-style: none; - text-align: center; - *zoom: 1; -} -.pager:before, -.pager:after { - display: table; - content: ""; - line-height: 0; -} -.pager:after { - clear: both; -} -.pager li { - display: inline; -} -.pager li > a, -.pager li > span { - display: inline-block; - padding: 5px 14px; - background-color: #fff; - border: 1px solid #ddd; - -webkit-border-radius: 15px; - -moz-border-radius: 15px; - border-radius: 15px; -} -.pager li > a:hover, -.pager li > a:focus { - text-decoration: none; - background-color: #f5f5f5; -} -.pager .next > a, -.pager .next > span { - float: right; -} -.pager .previous > a, -.pager .previous > span { - float: left; -} -.pager .disabled > a, -.pager .disabled > a:hover, -.pager .disabled > a:focus, -.pager .disabled > span { - color: #999999; - background-color: #fff; - cursor: default; -} -.modal-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1040; - background-color: #000000; -} -.modal-backdrop.fade { - opacity: 0; -} -.modal-backdrop, -.modal-backdrop.fade.in { - opacity: 0.8; - filter: alpha(opacity=80); -} -.modal { - position: fixed; - top: 10%; - left: 50%; - z-index: 1050; - width: 560px; - margin-left: -280px; - background-color: #ffffff; - border: 1px solid #999; - border: 1px solid rgba(0, 0, 0, 0.3); - *border: 1px solid #999; - /* IE6-7 */ - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - -webkit-background-clip: padding-box; - -moz-background-clip: padding-box; - background-clip: padding-box; - outline: none; -} -.modal.fade { - -webkit-transition: opacity .3s linear, top .3s ease-out; - -moz-transition: opacity .3s linear, top .3s ease-out; - -o-transition: opacity .3s linear, top .3s ease-out; - transition: opacity .3s linear, top .3s ease-out; - top: -25%; -} -.modal.fade.in { - top: 10%; -} -.modal-header { - padding: 9px 15px; - border-bottom: 1px solid #eee; -} -.modal-header .close { - margin-top: 2px; -} -.modal-header h3 { - margin: 0; - line-height: 30px; -} -.modal-body { - position: relative; - overflow-y: auto; - max-height: 400px; - padding: 15px; -} -.modal-form { - margin-bottom: 0; -} -.modal-footer { - padding: 14px 15px 15px; - margin-bottom: 0; - text-align: right; - background-color: #f5f5f5; - border-top: 1px solid #ddd; - -webkit-border-radius: 0 0 6px 6px; - -moz-border-radius: 0 0 6px 6px; - border-radius: 0 0 6px 6px; - -webkit-box-shadow: inset 0 1px 0 #ffffff; - -moz-box-shadow: inset 0 1px 0 #ffffff; - box-shadow: inset 0 1px 0 #ffffff; - *zoom: 1; -} -.modal-footer:before, -.modal-footer:after { - display: table; - content: ""; - line-height: 0; -} -.modal-footer:after { - clear: both; -} -.modal-footer .btn + .btn { - margin-left: 5px; - margin-bottom: 0; -} -.modal-footer .btn-group .btn + .btn { - margin-left: -1px; -} -.modal-footer .btn-block + .btn-block { - margin-left: 0; -} -.tooltip { - position: absolute; - z-index: 1030; - display: block; - visibility: visible; - font-size: 11px; - line-height: 1.4; - opacity: 0; - filter: alpha(opacity=0); -} -.tooltip.in { - opacity: 0.8; - filter: alpha(opacity=80); -} -.tooltip.top { - margin-top: -3px; - padding: 5px 0; -} -.tooltip.right { - margin-left: 3px; - padding: 0 5px; -} -.tooltip.bottom { - margin-top: 3px; - padding: 5px 0; -} -.tooltip.left { - margin-left: -3px; - padding: 0 5px; -} -.tooltip-inner { - max-width: 200px; - padding: 8px; - color: #ffffff; - text-align: center; - text-decoration: none; - background-color: #000000; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} -.tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} -.tooltip.top .tooltip-arrow { - bottom: 0; - left: 50%; - margin-left: -5px; - border-width: 5px 5px 0; - border-top-color: #000000; -} -.tooltip.right .tooltip-arrow { - top: 50%; - left: 0; - margin-top: -5px; - border-width: 5px 5px 5px 0; - border-right-color: #000000; -} -.tooltip.left .tooltip-arrow { - top: 50%; - right: 0; - margin-top: -5px; - border-width: 5px 0 5px 5px; - border-left-color: #000000; -} -.tooltip.bottom .tooltip-arrow { - top: 0; - left: 50%; - margin-left: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000000; -} -.popover { - position: absolute; - top: 0; - left: 0; - z-index: 1010; - display: none; - max-width: 276px; - padding: 1px; - text-align: left; - background-color: #ffffff; - -webkit-background-clip: padding-box; - -moz-background-clip: padding; - background-clip: padding-box; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.2); - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - white-space: normal; -} -.popover.top { - margin-top: -10px; -} -.popover.right { - margin-left: 10px; -} -.popover.bottom { - margin-top: 10px; -} -.popover.left { - margin-left: -10px; -} -.popover-title { - margin: 0; - padding: 8px 14px; - font-size: 14px; - font-weight: normal; - line-height: 18px; - background-color: #f7f7f7; - border-bottom: 1px solid #ebebeb; - -webkit-border-radius: 5px 5px 0 0; - -moz-border-radius: 5px 5px 0 0; - border-radius: 5px 5px 0 0; -} -.popover-title:empty { - display: none; -} -.popover-content { - padding: 9px 14px; -} -.popover .arrow, -.popover .arrow:after { - position: absolute; - display: block; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} -.popover .arrow { - border-width: 11px; -} -.popover .arrow:after { - border-width: 10px; - content: ""; -} -.popover.top .arrow { - left: 50%; - margin-left: -11px; - border-bottom-width: 0; - border-top-color: #999; - border-top-color: rgba(0, 0, 0, 0.25); - bottom: -11px; -} -.popover.top .arrow:after { - bottom: 1px; - margin-left: -10px; - border-bottom-width: 0; - border-top-color: #ffffff; -} -.popover.right .arrow { - top: 50%; - left: -11px; - margin-top: -11px; - border-left-width: 0; - border-right-color: #999; - border-right-color: rgba(0, 0, 0, 0.25); -} -.popover.right .arrow:after { - left: 1px; - bottom: -10px; - border-left-width: 0; - border-right-color: #ffffff; -} -.popover.bottom .arrow { - left: 50%; - margin-left: -11px; - border-top-width: 0; - border-bottom-color: #999; - border-bottom-color: rgba(0, 0, 0, 0.25); - top: -11px; -} -.popover.bottom .arrow:after { - top: 1px; - margin-left: -10px; - border-top-width: 0; - border-bottom-color: #ffffff; -} -.popover.left .arrow { - top: 50%; - right: -11px; - margin-top: -11px; - border-right-width: 0; - border-left-color: #999; - border-left-color: rgba(0, 0, 0, 0.25); -} -.popover.left .arrow:after { - right: 1px; - border-right-width: 0; - border-left-color: #ffffff; - bottom: -10px; -} -.thumbnails { - margin-left: -20px; - list-style: none; - *zoom: 1; -} -.thumbnails:before, -.thumbnails:after { - display: table; - content: ""; - line-height: 0; -} -.thumbnails:after { - clear: both; -} -.row-fluid .thumbnails { - margin-left: 0; -} -.thumbnails > li { - float: left; - margin-bottom: 20px; - margin-left: 20px; -} -.thumbnail { - display: block; - padding: 4px; - line-height: 20px; - border: 1px solid #ddd; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); - -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); - -webkit-transition: all 0.2s ease-in-out; - -moz-transition: all 0.2s ease-in-out; - -o-transition: all 0.2s ease-in-out; - transition: all 0.2s ease-in-out; -} -a.thumbnail:hover, -a.thumbnail:focus { - border-color: #0088cc; - -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); - -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); - box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); -} -.thumbnail > img { - display: block; - max-width: 100%; - margin-left: auto; - margin-right: auto; -} -.thumbnail .caption { - padding: 9px; - color: #555555; -} -.media, -.media-body { - overflow: hidden; - *overflow: visible; - zoom: 1; -} -.media, -.media .media { - margin-top: 15px; -} -.media:first-child { - margin-top: 0; -} -.media-object { - display: block; -} -.media-heading { - margin: 0 0 5px; -} -.media > .pull-left { - margin-right: 10px; -} -.media > .pull-right { - margin-left: 10px; -} -.media-list { - margin-left: 0; - list-style: none; -} -.label, -.badge { - display: inline-block; - padding: 2px 4px; - font-size: 11.844px; - font-weight: bold; - line-height: 14px; - color: #ffffff; - vertical-align: baseline; - white-space: nowrap; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #999999; -} -.label { - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} -.badge { - padding-left: 9px; - padding-right: 9px; - -webkit-border-radius: 9px; - -moz-border-radius: 9px; - border-radius: 9px; -} -.label:empty, -.badge:empty { - display: none; -} -a.label:hover, -a.label:focus, -a.badge:hover, -a.badge:focus { - color: #ffffff; - text-decoration: none; - cursor: pointer; -} -.label-important, -.badge-important { - background-color: #b94a48; -} -.label-important[href], -.badge-important[href] { - background-color: #953b39; -} -.label-warning, -.badge-warning { - background-color: #f89406; -} -.label-warning[href], -.badge-warning[href] { - background-color: #c67605; -} -.label-success, -.badge-success { - background-color: #468847; -} -.label-success[href], -.badge-success[href] { - background-color: #356635; -} -.label-info, -.badge-info { - background-color: #3a87ad; -} -.label-info[href], -.badge-info[href] { - background-color: #2d6987; -} -.label-inverse, -.badge-inverse { - background-color: #333333; -} -.label-inverse[href], -.badge-inverse[href] { - background-color: #1a1a1a; -} -.btn .label, -.btn .badge { - position: relative; - top: -1px; -} -.btn-mini .label, -.btn-mini .badge { - top: 0; -} -@-webkit-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -@-moz-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -@-ms-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -@-o-keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} -@keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -.progress { - overflow: hidden; - height: 20px; - margin-bottom: 20px; - background-color: #f7f7f7; - background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); - background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0); - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} -.progress .bar { - width: 0%; - height: 100%; - color: #ffffff; - float: left; - font-size: 12px; - text-align: center; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #0e90d2; - background-image: -moz-linear-gradient(top, #149bdf, #0480be); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); - background-image: -webkit-linear-gradient(top, #149bdf, #0480be); - background-image: -o-linear-gradient(top, #149bdf, #0480be); - background-image: linear-gradient(to bottom, #149bdf, #0480be); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0); - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - -webkit-transition: width 0.6s ease; - -moz-transition: width 0.6s ease; - -o-transition: width 0.6s ease; - transition: width 0.6s ease; -} -.progress .bar + .bar { - -webkit-box-shadow: inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15); - -moz-box-shadow: inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15); - box-shadow: inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15); -} -.progress-striped .bar { - background-color: #149bdf; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - -webkit-background-size: 40px 40px; - -moz-background-size: 40px 40px; - -o-background-size: 40px 40px; - background-size: 40px 40px; -} -.progress.active .bar { - -webkit-animation: progress-bar-stripes 2s linear infinite; - -moz-animation: progress-bar-stripes 2s linear infinite; - -ms-animation: progress-bar-stripes 2s linear infinite; - -o-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite; -} -.progress-danger .bar, -.progress .bar-danger { - background-color: #dd514c; - background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); - background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); - background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); - background-image: linear-gradient(to bottom, #ee5f5b, #c43c35); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0); -} -.progress-danger.progress-striped .bar, -.progress-striped .bar-danger { - background-color: #ee5f5b; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} -.progress-success .bar, -.progress .bar-success { - background-color: #5eb95e; - background-image: -moz-linear-gradient(top, #62c462, #57a957); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); - background-image: -webkit-linear-gradient(top, #62c462, #57a957); - background-image: -o-linear-gradient(top, #62c462, #57a957); - background-image: linear-gradient(to bottom, #62c462, #57a957); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0); -} -.progress-success.progress-striped .bar, -.progress-striped .bar-success { - background-color: #62c462; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} -.progress-info .bar, -.progress .bar-info { - background-color: #4bb1cf; - background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); - background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); - background-image: -o-linear-gradient(top, #5bc0de, #339bb9); - background-image: linear-gradient(to bottom, #5bc0de, #339bb9); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0); -} -.progress-info.progress-striped .bar, -.progress-striped .bar-info { - background-color: #5bc0de; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} -.progress-warning .bar, -.progress .bar-warning { - background-color: #faa732; - background-image: -moz-linear-gradient(top, #fbb450, #f89406); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); - background-image: -webkit-linear-gradient(top, #fbb450, #f89406); - background-image: -o-linear-gradient(top, #fbb450, #f89406); - background-image: linear-gradient(to bottom, #fbb450, #f89406); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); -} -.progress-warning.progress-striped .bar, -.progress-striped .bar-warning { - background-color: #fbb450; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} -.accordion { - margin-bottom: 20px; -} -.accordion-group { - margin-bottom: 2px; - border: 1px solid #e5e5e5; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} -.accordion-heading { - border-bottom: 0; -} -.accordion-heading .accordion-toggle { - display: block; - padding: 8px 15px; -} -.accordion-toggle { - cursor: pointer; -} -.accordion-inner { - padding: 9px 15px; - border-top: 1px solid #e5e5e5; -} -.carousel { - position: relative; - margin-bottom: 20px; - line-height: 1; -} -.carousel-inner { - overflow: hidden; - width: 100%; - position: relative; -} -.carousel-inner > .item { - display: none; - position: relative; - -webkit-transition: 0.6s ease-in-out left; - -moz-transition: 0.6s ease-in-out left; - -o-transition: 0.6s ease-in-out left; - transition: 0.6s ease-in-out left; -} -.carousel-inner > .item > img, -.carousel-inner > .item > a > img { - display: block; - line-height: 1; -} -.carousel-inner > .active, -.carousel-inner > .next, -.carousel-inner > .prev { - display: block; -} -.carousel-inner > .active { - left: 0; -} -.carousel-inner > .next, -.carousel-inner > .prev { - position: absolute; - top: 0; - width: 100%; -} -.carousel-inner > .next { - left: 100%; -} -.carousel-inner > .prev { - left: -100%; -} -.carousel-inner > .next.left, -.carousel-inner > .prev.right { - left: 0; -} -.carousel-inner > .active.left { - left: -100%; -} -.carousel-inner > .active.right { - left: 100%; -} -.carousel-control { - position: absolute; - top: 40%; - left: 15px; - width: 40px; - height: 40px; - margin-top: -20px; - font-size: 60px; - font-weight: 100; - line-height: 30px; - color: #ffffff; - text-align: center; - background: #222222; - border: 3px solid #ffffff; - -webkit-border-radius: 23px; - -moz-border-radius: 23px; - border-radius: 23px; - opacity: 0.5; - filter: alpha(opacity=50); -} -.carousel-control.right { - left: auto; - right: 15px; -} -.carousel-control:hover, -.carousel-control:focus { - color: #ffffff; - text-decoration: none; - opacity: 0.9; - filter: alpha(opacity=90); -} -.carousel-indicators { - position: absolute; - top: 15px; - right: 15px; - z-index: 5; - margin: 0; - list-style: none; -} -.carousel-indicators li { - display: block; - float: left; - width: 10px; - height: 10px; - margin-left: 5px; - text-indent: -999px; - background-color: #ccc; - background-color: rgba(255, 255, 255, 0.25); - border-radius: 5px; -} -.carousel-indicators .active { - background-color: #fff; -} -.carousel-caption { - position: absolute; - left: 0; - right: 0; - bottom: 0; - padding: 15px; - background: #333333; - background: rgba(0, 0, 0, 0.75); -} -.carousel-caption h4, -.carousel-caption p { - color: #ffffff; - line-height: 20px; -} -.carousel-caption h4 { - margin: 0 0 5px; -} -.carousel-caption p { - margin-bottom: 0; -} -.hero-unit { - padding: 60px; - margin-bottom: 30px; - font-size: 18px; - font-weight: 200; - line-height: 30px; - color: inherit; - background-color: #eeeeee; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} -.hero-unit h1 { - margin-bottom: 0; - font-size: 60px; - line-height: 1; - color: inherit; - letter-spacing: -1px; -} -.hero-unit li { - line-height: 30px; -} -.pull-right { - float: right; -} -.pull-left { - float: left; -} -.hide { - display: none; -} -.show { - display: block; -} -.invisible { - visibility: hidden; -} -.affix { - position: fixed; -} - From fd8f628a4fb23e0e338880622916f26fe75870a2 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 17 Mar 2017 16:33:48 -0400 Subject: [PATCH 360/465] generate .css files and put them into the source directory --- .gitignore | 2 ++ openid-connect-server-webapp/pom.xml | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index cc7301fd52..a403cd3d80 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,5 @@ bin /target .springBeans nb-configuration.xml +openid-connect-server-webapp/src/main/webapp/resources/bootstrap2/css/bootstrap-responsive.css +openid-connect-server-webapp/src/main/webapp/resources/bootstrap2/css/bootstrap.css diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index 141cf54bf8..68059590fd 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -88,7 +88,7 @@ lesscss-maven-plugin ${project.basedir}/src/main/less - ${project.build.directory}/${project.build.finalName}/resources/bootstrap2/css + ${project.basedir}/src/main/webapp/resources/bootstrap2/css false bootstrap.less @@ -100,6 +100,7 @@ compile + process-sources From 9b2177a4223563f68d6ddd8881828402ff76c90d Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 17 Mar 2017 17:52:33 -0400 Subject: [PATCH 361/465] =?UTF-8?q?switched=20to=20using=20wro4j,=20main?= =?UTF-8?q?=20file=20works=20but=20responsive=20file=20doesn=E2=80=99t?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- openid-connect-server-webapp/pom.xml | 33 +++++++++++-------- .../src/main/webapp/WEB-INF/wro.properties | 2 ++ .../src/main/webapp/WEB-INF/wro.xml | 6 ++++ .../src/main/{ => webapp}/less/accordion.less | 0 .../src/main/{ => webapp}/less/alerts.less | 0 .../less/bootstrap-responsive.less | 0 .../src/main/{ => webapp}/less/bootstrap.less | 0 .../main/{ => webapp}/less/breadcrumbs.less | 0 .../main/{ => webapp}/less/button-groups.less | 0 .../src/main/{ => webapp}/less/buttons.less | 0 .../src/main/{ => webapp}/less/carousel.less | 0 .../src/main/{ => webapp}/less/close.less | 0 .../src/main/{ => webapp}/less/code.less | 0 .../less/component-animations.less | 0 .../src/main/{ => webapp}/less/dropdowns.less | 0 .../src/main/{ => webapp}/less/forms.less | 0 .../src/main/{ => webapp}/less/grid.less | 0 .../src/main/{ => webapp}/less/hero-unit.less | 0 .../main/{ => webapp}/less/labels-badges.less | 0 .../src/main/{ => webapp}/less/layouts.less | 0 .../src/main/{ => webapp}/less/media.less | 0 .../src/main/{ => webapp}/less/mixins.less | 0 .../src/main/{ => webapp}/less/modals.less | 0 .../src/main/{ => webapp}/less/navbar.less | 0 .../src/main/{ => webapp}/less/navs.less | 0 .../src/main/{ => webapp}/less/pager.less | 0 .../main/{ => webapp}/less/pagination.less | 0 .../src/main/{ => webapp}/less/popovers.less | 0 .../main/{ => webapp}/less/progress-bars.less | 0 .../src/main/{ => webapp}/less/reset.less | 0 .../less/responsive-1200px-min.less | 0 .../less/responsive-767px-max.less | 0 .../less/responsive-768px-979px.less | 0 .../{ => webapp}/less/responsive-navbar.less | 0 .../less/responsive-utilities.less | 0 .../main/{ => webapp}/less/scaffolding.less | 0 .../src/main/{ => webapp}/less/sprites.less | 0 .../src/main/{ => webapp}/less/tables.less | 0 .../main/{ => webapp}/less/thumbnails.less | 0 .../src/main/{ => webapp}/less/tooltip.less | 0 .../src/main/{ => webapp}/less/type.less | 0 .../src/main/{ => webapp}/less/utilities.less | 0 .../src/main/{ => webapp}/less/variables.less | 0 .../src/main/{ => webapp}/less/wells.less | 0 44 files changed, 27 insertions(+), 14 deletions(-) create mode 100644 openid-connect-server-webapp/src/main/webapp/WEB-INF/wro.properties create mode 100644 openid-connect-server-webapp/src/main/webapp/WEB-INF/wro.xml rename openid-connect-server-webapp/src/main/{ => webapp}/less/accordion.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/alerts.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/bootstrap-responsive.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/bootstrap.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/breadcrumbs.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/button-groups.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/buttons.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/carousel.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/close.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/code.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/component-animations.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/dropdowns.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/forms.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/grid.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/hero-unit.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/labels-badges.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/layouts.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/media.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/mixins.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/modals.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/navbar.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/navs.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/pager.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/pagination.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/popovers.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/progress-bars.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/reset.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/responsive-1200px-min.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/responsive-767px-max.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/responsive-768px-979px.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/responsive-navbar.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/responsive-utilities.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/scaffolding.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/sprites.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/tables.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/thumbnails.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/tooltip.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/type.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/utilities.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/variables.less (100%) rename openid-connect-server-webapp/src/main/{ => webapp}/less/wells.less (100%) diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index 68059590fd..b3eaa31b60 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -84,30 +84,35 @@ - org.lesscss - lesscss-maven-plugin - - ${project.basedir}/src/main/less - ${project.basedir}/src/main/webapp/resources/bootstrap2/css - false - - bootstrap.less - bootstrap-responsive.less - - + ro.isdc.wro4j + wro4j-maven-plugin + 1.8.0 + compile - compile + run - process-sources + + bootstrap + ${project.build.directory}/${project.build.finalName} + ${project.build.directory}/${project.build.finalName}/resources/bootstrap2/css/ + ${project.build.directory}/${project.build.finalName}/js/ + ro.isdc.wro.maven.plugin.manager.factory.ConfigurableWroManagerFactory + + - + + ro.isdc.wro4j + wro4j-extensions + 1.8.0 + + org.mitre openid-connect-server diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/wro.properties b/openid-connect-server-webapp/src/main/webapp/WEB-INF/wro.properties new file mode 100644 index 0000000000..8b8c9dd890 --- /dev/null +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/wro.properties @@ -0,0 +1,2 @@ +preProcessors=cssImport +postProcessors=lessCss diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/wro.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/wro.xml new file mode 100644 index 0000000000..a69a55bb9f --- /dev/null +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/wro.xml @@ -0,0 +1,6 @@ + + + /less/bootstrap.less + /less/bootstrap-responsive.less + + \ No newline at end of file diff --git a/openid-connect-server-webapp/src/main/less/accordion.less b/openid-connect-server-webapp/src/main/webapp/less/accordion.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/accordion.less rename to openid-connect-server-webapp/src/main/webapp/less/accordion.less diff --git a/openid-connect-server-webapp/src/main/less/alerts.less b/openid-connect-server-webapp/src/main/webapp/less/alerts.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/alerts.less rename to openid-connect-server-webapp/src/main/webapp/less/alerts.less diff --git a/openid-connect-server-webapp/src/main/less/bootstrap-responsive.less b/openid-connect-server-webapp/src/main/webapp/less/bootstrap-responsive.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/bootstrap-responsive.less rename to openid-connect-server-webapp/src/main/webapp/less/bootstrap-responsive.less diff --git a/openid-connect-server-webapp/src/main/less/bootstrap.less b/openid-connect-server-webapp/src/main/webapp/less/bootstrap.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/bootstrap.less rename to openid-connect-server-webapp/src/main/webapp/less/bootstrap.less diff --git a/openid-connect-server-webapp/src/main/less/breadcrumbs.less b/openid-connect-server-webapp/src/main/webapp/less/breadcrumbs.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/breadcrumbs.less rename to openid-connect-server-webapp/src/main/webapp/less/breadcrumbs.less diff --git a/openid-connect-server-webapp/src/main/less/button-groups.less b/openid-connect-server-webapp/src/main/webapp/less/button-groups.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/button-groups.less rename to openid-connect-server-webapp/src/main/webapp/less/button-groups.less diff --git a/openid-connect-server-webapp/src/main/less/buttons.less b/openid-connect-server-webapp/src/main/webapp/less/buttons.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/buttons.less rename to openid-connect-server-webapp/src/main/webapp/less/buttons.less diff --git a/openid-connect-server-webapp/src/main/less/carousel.less b/openid-connect-server-webapp/src/main/webapp/less/carousel.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/carousel.less rename to openid-connect-server-webapp/src/main/webapp/less/carousel.less diff --git a/openid-connect-server-webapp/src/main/less/close.less b/openid-connect-server-webapp/src/main/webapp/less/close.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/close.less rename to openid-connect-server-webapp/src/main/webapp/less/close.less diff --git a/openid-connect-server-webapp/src/main/less/code.less b/openid-connect-server-webapp/src/main/webapp/less/code.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/code.less rename to openid-connect-server-webapp/src/main/webapp/less/code.less diff --git a/openid-connect-server-webapp/src/main/less/component-animations.less b/openid-connect-server-webapp/src/main/webapp/less/component-animations.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/component-animations.less rename to openid-connect-server-webapp/src/main/webapp/less/component-animations.less diff --git a/openid-connect-server-webapp/src/main/less/dropdowns.less b/openid-connect-server-webapp/src/main/webapp/less/dropdowns.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/dropdowns.less rename to openid-connect-server-webapp/src/main/webapp/less/dropdowns.less diff --git a/openid-connect-server-webapp/src/main/less/forms.less b/openid-connect-server-webapp/src/main/webapp/less/forms.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/forms.less rename to openid-connect-server-webapp/src/main/webapp/less/forms.less diff --git a/openid-connect-server-webapp/src/main/less/grid.less b/openid-connect-server-webapp/src/main/webapp/less/grid.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/grid.less rename to openid-connect-server-webapp/src/main/webapp/less/grid.less diff --git a/openid-connect-server-webapp/src/main/less/hero-unit.less b/openid-connect-server-webapp/src/main/webapp/less/hero-unit.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/hero-unit.less rename to openid-connect-server-webapp/src/main/webapp/less/hero-unit.less diff --git a/openid-connect-server-webapp/src/main/less/labels-badges.less b/openid-connect-server-webapp/src/main/webapp/less/labels-badges.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/labels-badges.less rename to openid-connect-server-webapp/src/main/webapp/less/labels-badges.less diff --git a/openid-connect-server-webapp/src/main/less/layouts.less b/openid-connect-server-webapp/src/main/webapp/less/layouts.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/layouts.less rename to openid-connect-server-webapp/src/main/webapp/less/layouts.less diff --git a/openid-connect-server-webapp/src/main/less/media.less b/openid-connect-server-webapp/src/main/webapp/less/media.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/media.less rename to openid-connect-server-webapp/src/main/webapp/less/media.less diff --git a/openid-connect-server-webapp/src/main/less/mixins.less b/openid-connect-server-webapp/src/main/webapp/less/mixins.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/mixins.less rename to openid-connect-server-webapp/src/main/webapp/less/mixins.less diff --git a/openid-connect-server-webapp/src/main/less/modals.less b/openid-connect-server-webapp/src/main/webapp/less/modals.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/modals.less rename to openid-connect-server-webapp/src/main/webapp/less/modals.less diff --git a/openid-connect-server-webapp/src/main/less/navbar.less b/openid-connect-server-webapp/src/main/webapp/less/navbar.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/navbar.less rename to openid-connect-server-webapp/src/main/webapp/less/navbar.less diff --git a/openid-connect-server-webapp/src/main/less/navs.less b/openid-connect-server-webapp/src/main/webapp/less/navs.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/navs.less rename to openid-connect-server-webapp/src/main/webapp/less/navs.less diff --git a/openid-connect-server-webapp/src/main/less/pager.less b/openid-connect-server-webapp/src/main/webapp/less/pager.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/pager.less rename to openid-connect-server-webapp/src/main/webapp/less/pager.less diff --git a/openid-connect-server-webapp/src/main/less/pagination.less b/openid-connect-server-webapp/src/main/webapp/less/pagination.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/pagination.less rename to openid-connect-server-webapp/src/main/webapp/less/pagination.less diff --git a/openid-connect-server-webapp/src/main/less/popovers.less b/openid-connect-server-webapp/src/main/webapp/less/popovers.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/popovers.less rename to openid-connect-server-webapp/src/main/webapp/less/popovers.less diff --git a/openid-connect-server-webapp/src/main/less/progress-bars.less b/openid-connect-server-webapp/src/main/webapp/less/progress-bars.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/progress-bars.less rename to openid-connect-server-webapp/src/main/webapp/less/progress-bars.less diff --git a/openid-connect-server-webapp/src/main/less/reset.less b/openid-connect-server-webapp/src/main/webapp/less/reset.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/reset.less rename to openid-connect-server-webapp/src/main/webapp/less/reset.less diff --git a/openid-connect-server-webapp/src/main/less/responsive-1200px-min.less b/openid-connect-server-webapp/src/main/webapp/less/responsive-1200px-min.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/responsive-1200px-min.less rename to openid-connect-server-webapp/src/main/webapp/less/responsive-1200px-min.less diff --git a/openid-connect-server-webapp/src/main/less/responsive-767px-max.less b/openid-connect-server-webapp/src/main/webapp/less/responsive-767px-max.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/responsive-767px-max.less rename to openid-connect-server-webapp/src/main/webapp/less/responsive-767px-max.less diff --git a/openid-connect-server-webapp/src/main/less/responsive-768px-979px.less b/openid-connect-server-webapp/src/main/webapp/less/responsive-768px-979px.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/responsive-768px-979px.less rename to openid-connect-server-webapp/src/main/webapp/less/responsive-768px-979px.less diff --git a/openid-connect-server-webapp/src/main/less/responsive-navbar.less b/openid-connect-server-webapp/src/main/webapp/less/responsive-navbar.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/responsive-navbar.less rename to openid-connect-server-webapp/src/main/webapp/less/responsive-navbar.less diff --git a/openid-connect-server-webapp/src/main/less/responsive-utilities.less b/openid-connect-server-webapp/src/main/webapp/less/responsive-utilities.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/responsive-utilities.less rename to openid-connect-server-webapp/src/main/webapp/less/responsive-utilities.less diff --git a/openid-connect-server-webapp/src/main/less/scaffolding.less b/openid-connect-server-webapp/src/main/webapp/less/scaffolding.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/scaffolding.less rename to openid-connect-server-webapp/src/main/webapp/less/scaffolding.less diff --git a/openid-connect-server-webapp/src/main/less/sprites.less b/openid-connect-server-webapp/src/main/webapp/less/sprites.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/sprites.less rename to openid-connect-server-webapp/src/main/webapp/less/sprites.less diff --git a/openid-connect-server-webapp/src/main/less/tables.less b/openid-connect-server-webapp/src/main/webapp/less/tables.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/tables.less rename to openid-connect-server-webapp/src/main/webapp/less/tables.less diff --git a/openid-connect-server-webapp/src/main/less/thumbnails.less b/openid-connect-server-webapp/src/main/webapp/less/thumbnails.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/thumbnails.less rename to openid-connect-server-webapp/src/main/webapp/less/thumbnails.less diff --git a/openid-connect-server-webapp/src/main/less/tooltip.less b/openid-connect-server-webapp/src/main/webapp/less/tooltip.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/tooltip.less rename to openid-connect-server-webapp/src/main/webapp/less/tooltip.less diff --git a/openid-connect-server-webapp/src/main/less/type.less b/openid-connect-server-webapp/src/main/webapp/less/type.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/type.less rename to openid-connect-server-webapp/src/main/webapp/less/type.less diff --git a/openid-connect-server-webapp/src/main/less/utilities.less b/openid-connect-server-webapp/src/main/webapp/less/utilities.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/utilities.less rename to openid-connect-server-webapp/src/main/webapp/less/utilities.less diff --git a/openid-connect-server-webapp/src/main/less/variables.less b/openid-connect-server-webapp/src/main/webapp/less/variables.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/variables.less rename to openid-connect-server-webapp/src/main/webapp/less/variables.less diff --git a/openid-connect-server-webapp/src/main/less/wells.less b/openid-connect-server-webapp/src/main/webapp/less/wells.less similarity index 100% rename from openid-connect-server-webapp/src/main/less/wells.less rename to openid-connect-server-webapp/src/main/webapp/less/wells.less From eb1ec0979d4f43cc3c837e4898839b7c5fd6c154 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Sat, 18 Mar 2017 10:59:30 -0400 Subject: [PATCH 362/465] separated root bootstrap and responsive files into different WRO4J groups --- openid-connect-server-webapp/pom.xml | 2 +- openid-connect-server-webapp/src/main/webapp/WEB-INF/wro.xml | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index b3eaa31b60..96fbcc7b7c 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -96,7 +96,7 @@ - bootstrap + bootstrap,bootstrap-responsive ${project.build.directory}/${project.build.finalName} ${project.build.directory}/${project.build.finalName}/resources/bootstrap2/css/ ${project.build.directory}/${project.build.finalName}/js/ diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/wro.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/wro.xml index a69a55bb9f..fdd66a0b40 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/wro.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/wro.xml @@ -1,6 +1,8 @@ /less/bootstrap.less + + /less/bootstrap-responsive.less - + \ No newline at end of file From 4da1e619a075388922fb9be98e28b1039731fd45 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Sat, 18 Mar 2017 11:24:01 -0400 Subject: [PATCH 363/465] plugin management, removed less files from .war --- openid-connect-server-webapp/pom.xml | 11 +---------- pom.xml | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index 96fbcc7b7c..df16b8c83b 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -58,6 +58,7 @@ + less/** @@ -86,15 +87,6 @@ ro.isdc.wro4j wro4j-maven-plugin - 1.8.0 - - - compile - - run - - - bootstrap,bootstrap-responsive ${project.build.directory}/${project.build.finalName} @@ -110,7 +102,6 @@ ro.isdc.wro4j wro4j-extensions - 1.8.0 org.mitre diff --git a/pom.xml b/pom.xml index 9b9d7e443e..65d3e18eb0 100644 --- a/pom.xml +++ b/pom.xml @@ -150,6 +150,19 @@ + + ro.isdc.wro4j + wro4j-maven-plugin + 1.8.0 + + + compile + + run + + + + @@ -568,6 +581,11 @@ commons-io 1.3.2 + + ro.isdc.wro4j + wro4j-extensions + 1.8.0 + From 80358566a55a1335137b146bf1a4c149bb107017 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 20 Mar 2017 11:58:52 -0400 Subject: [PATCH 364/465] [maven-release-plugin] prepare release mitreid-connect-1.3.0-RC2 --- openid-connect-client/pom.xml | 2 +- openid-connect-common/pom.xml | 2 +- openid-connect-server-webapp/pom.xml | 2 +- openid-connect-server/pom.xml | 2 +- pom.xml | 2 +- uma-server-webapp/pom.xml | 2 +- uma-server/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/openid-connect-client/pom.xml b/openid-connect-client/pom.xml index a42644801c..eb5b36b3f4 100644 --- a/openid-connect-client/pom.xml +++ b/openid-connect-client/pom.xml @@ -21,7 +21,7 @@ openid-connect-parent org.mitre - 1.3.0-RC2-SNAPSHOT + 1.3.0-RC2 .. openid-connect-client diff --git a/openid-connect-common/pom.xml b/openid-connect-common/pom.xml index 50cb25e7f7..966ae2d689 100644 --- a/openid-connect-common/pom.xml +++ b/openid-connect-common/pom.xml @@ -21,7 +21,7 @@ openid-connect-parent org.mitre - 1.3.0-RC2-SNAPSHOT + 1.3.0-RC2 .. openid-connect-common diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index df16b8c83b..f95fcd6b6b 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.3.0-RC2-SNAPSHOT + 1.3.0-RC2 openid-connect-server-webapp war diff --git a/openid-connect-server/pom.xml b/openid-connect-server/pom.xml index c7e47dfdf7..dd58b79fe8 100644 --- a/openid-connect-server/pom.xml +++ b/openid-connect-server/pom.xml @@ -22,7 +22,7 @@ org.mitre openid-connect-parent - 1.3.0-RC2-SNAPSHOT + 1.3.0-RC2 .. diff --git a/pom.xml b/pom.xml index 65d3e18eb0..c0a1edb340 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ 4.0.0 org.mitre openid-connect-parent - 1.3.0-RC2-SNAPSHOT + 1.3.0-RC2 MITREid Connect pom diff --git a/uma-server-webapp/pom.xml b/uma-server-webapp/pom.xml index 00cec856eb..ea7cc3d7b6 100644 --- a/uma-server-webapp/pom.xml +++ b/uma-server-webapp/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.3.0-RC2-SNAPSHOT + 1.3.0-RC2 .. uma-server-webapp diff --git a/uma-server/pom.xml b/uma-server/pom.xml index 6ac6925e81..623ad7a489 100644 --- a/uma-server/pom.xml +++ b/uma-server/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.3.0-RC2-SNAPSHOT + 1.3.0-RC2 .. uma-server From dd0f69ba6d0309500d47520025a5b0a6e73d6057 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 20 Mar 2017 11:58:58 -0400 Subject: [PATCH 365/465] [maven-release-plugin] prepare for next development iteration --- openid-connect-client/pom.xml | 2 +- openid-connect-common/pom.xml | 2 +- openid-connect-server-webapp/pom.xml | 2 +- openid-connect-server/pom.xml | 2 +- pom.xml | 2 +- uma-server-webapp/pom.xml | 2 +- uma-server/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/openid-connect-client/pom.xml b/openid-connect-client/pom.xml index eb5b36b3f4..d22283da7e 100644 --- a/openid-connect-client/pom.xml +++ b/openid-connect-client/pom.xml @@ -21,7 +21,7 @@ openid-connect-parent org.mitre - 1.3.0-RC2 + 1.3.0-RC3-SNAPSHOT .. openid-connect-client diff --git a/openid-connect-common/pom.xml b/openid-connect-common/pom.xml index 966ae2d689..5edafd5c34 100644 --- a/openid-connect-common/pom.xml +++ b/openid-connect-common/pom.xml @@ -21,7 +21,7 @@ openid-connect-parent org.mitre - 1.3.0-RC2 + 1.3.0-RC3-SNAPSHOT .. openid-connect-common diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index f95fcd6b6b..528201c049 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.3.0-RC2 + 1.3.0-RC3-SNAPSHOT openid-connect-server-webapp war diff --git a/openid-connect-server/pom.xml b/openid-connect-server/pom.xml index dd58b79fe8..96ad23d087 100644 --- a/openid-connect-server/pom.xml +++ b/openid-connect-server/pom.xml @@ -22,7 +22,7 @@ org.mitre openid-connect-parent - 1.3.0-RC2 + 1.3.0-RC3-SNAPSHOT .. diff --git a/pom.xml b/pom.xml index c0a1edb340..a8bbcf5e82 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ 4.0.0 org.mitre openid-connect-parent - 1.3.0-RC2 + 1.3.0-RC3-SNAPSHOT MITREid Connect pom diff --git a/uma-server-webapp/pom.xml b/uma-server-webapp/pom.xml index ea7cc3d7b6..81f4705057 100644 --- a/uma-server-webapp/pom.xml +++ b/uma-server-webapp/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.3.0-RC2 + 1.3.0-RC3-SNAPSHOT .. uma-server-webapp diff --git a/uma-server/pom.xml b/uma-server/pom.xml index 623ad7a489..5bfde7812e 100644 --- a/uma-server/pom.xml +++ b/uma-server/pom.xml @@ -20,7 +20,7 @@ org.mitre openid-connect-parent - 1.3.0-RC2 + 1.3.0-RC3-SNAPSHOT .. uma-server From b6cf8fe22be7cbf952341fa3a2286ab16b3fad3a Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 20 Mar 2017 13:45:55 -0400 Subject: [PATCH 366/465] cleanup --- .gitignore | 3 --- LICENSE.txt | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index a403cd3d80..e663c16b8f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -local-values.conf target *~ bin @@ -11,5 +10,3 @@ bin /target .springBeans nb-configuration.xml -openid-connect-server-webapp/src/main/webapp/resources/bootstrap2/css/bootstrap-responsive.css -openid-connect-server-webapp/src/main/webapp/resources/bootstrap2/css/bootstrap.css diff --git a/LICENSE.txt b/LICENSE.txt index 093874f21f..12d29da560 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright 2016 The MITRE Corporation +Copyright 2017 The MITRE Corporation and the MIT Internet Trust Consortium Licensed under the Apache License, Version 2.0 (the "License"); From 32ce21b5cd7fa9cbdefa89bd723d8ef5ba8d74ae Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 21 Mar 2017 13:36:20 -0400 Subject: [PATCH 367/465] automated code formatting and cleanup --- .../IntrospectingTokenService.java | 4 +- .../IntrospectionAuthorityGranter.java | 2 +- .../IntrospectionConfigurationService.java | 2 +- ...singIntrospectionConfigurationService.java | 6 +- ...eBasedIntrospectionAuthoritiesGranter.java | 6 +- .../SimpleIntrospectionAuthorityGranter.java | 6 +- ...aticIntrospectionConfigurationService.java | 6 +- .../AuthorizationEndpointException.java | 4 +- .../client/NamedAdminAuthoritiesMapper.java | 8 +- .../client/OIDCAuthenticationFilter.java | 32 +- .../client/OIDCAuthenticationProvider.java | 8 +- .../StaticPrefixTargetLinkURIChecker.java | 2 +- .../client/SubjectIssuerGrantedAuthority.java | 10 +- .../connect/client/TargetLinkURIChecker.java | 2 +- .../connect/client/UserInfoFetcher.java | 21 +- .../ClientKeyPublisherMapping.java | 2 +- .../client/keypublisher/JwkViewResolver.java | 6 +- .../client/model/IssuerServiceResponse.java | 6 +- .../service/AuthRequestOptionsService.java | 10 +- .../client/service/AuthRequestUrlBuilder.java | 4 +- .../service/ClientConfigurationService.java | 2 +- .../connect/client/service/IssuerService.java | 6 +- .../service/RegisteredClientService.java | 4 +- .../service/ServerConfigurationService.java | 2 +- ...egistrationClientConfigurationService.java | 16 +- .../DynamicServerConfigurationService.java | 26 +- .../impl/EncryptedAuthRequestUrlBuilder.java | 2 +- .../HybridClientConfigurationService.java | 8 +- .../service/impl/HybridIssuerService.java | 4 +- .../HybridServerConfigurationService.java | 8 +- .../impl/InMemoryRegisteredClientService.java | 2 +- .../impl/JsonFileRegisteredClientService.java | 30 +- .../impl/PlainAuthRequestUrlBuilder.java | 6 +- .../impl/SignedAuthRequestUrlBuilder.java | 2 +- .../impl/StaticAuthRequestOptionsService.java | 6 +- .../StaticClientConfigurationService.java | 8 +- .../StaticServerConfigurationService.java | 4 +- .../impl/StaticSingleIssuerService.java | 4 +- .../service/impl/ThirdPartyIssuerService.java | 6 +- .../service/impl/WebfingerIssuerService.java | 10 +- ...eBasedIntrospectionAuthoritiesGranter.java | 14 +- .../client/TestOIDCAuthenticationFilter.java | 22 +- .../impl/TestSignedAuthRequestUrlBuilder.java | 2 +- .../data/AbstractPageOperationTemplate.java | 318 +++---- .../org/mitre/data/DefaultPageCriteria.java | 38 +- .../java/org/mitre/data/PageCriteria.java | 4 +- .../util/WebfingerURLNormalizer.java | 2 +- .../mitre/jose/keystore/JWKSetKeyStore.java | 2 +- .../jwt/assertion/AssertionValidator.java | 2 +- .../impl/NullAssertionValidator.java | 2 +- .../impl/SelfAssertionValidator.java | 14 +- .../WhitelistedIssuerAssertionValidator.java | 20 +- ...aultJWTEncryptionAndDecryptionService.java | 11 +- .../JWTSigningAndValidationService.java | 6 +- .../service/impl/ClientKeyCacheService.java | 4 +- ...DefaultJWTSigningAndValidationService.java | 28 +- .../service/impl/JWKSetCacheService.java | 14 +- .../SymmetricKeyJWTValidatorCacheService.java | 4 +- .../oauth2/model/AuthorizationCodeEntity.java | 4 +- .../oauth2/model/ClientDetailsEntity.java | 21 +- .../org/mitre/oauth2/model/DeviceCode.java | 14 +- .../oauth2/model/OAuth2AccessTokenEntity.java | 9 +- .../model/OAuth2RefreshTokenEntity.java | 6 +- .../org/mitre/oauth2/model/PKCEAlgorithm.java | 15 +- .../mitre/oauth2/model/RegisteredClient.java | 6 +- .../oauth2/model/SavedUserAuthentication.java | 2 +- .../org/mitre/oauth2/model/SystemScope.java | 3 +- .../convert/SerializableStringConverter.java | 4 +- .../AuthenticationHolderRepository.java | 2 +- .../AuthorizationCodeRepository.java | 18 +- .../repository/OAuth2TokenRepository.java | 46 +- .../repository/SystemScopeRepository.java | 2 +- .../repository/impl/DeviceCodeRepository.java | 1 - .../oauth2/service/DeviceCodeService.java | 3 +- .../oauth2/service/SystemScopeService.java | 16 +- .../impl/DefaultClientUserDetailsService.java | 6 +- .../UriEncodedClientUserDetailsService.java | 6 +- .../ClientDetailsEntityJsonProcessor.java | 36 +- .../ConfigurationBeanLocaleResolver.java | 7 +- .../config/ConfigurationPropertiesBean.java | 84 +- .../openid/connect/config/JWKSetEditor.java | 2 +- .../connect/config/ServerConfiguration.java | 8 +- .../connect/config/UIConfiguration.java | 8 +- .../mitre/openid/connect/model/Address.java | 24 +- .../openid/connect/model/ApprovedSite.java | 6 - .../openid/connect/model/BlacklistedSite.java | 2 +- .../openid/connect/model/CachedImage.java | 4 +- .../openid/connect/model/ClientStat.java | 2 +- .../openid/connect/model/DefaultAddress.java | 15 +- .../openid/connect/model/DefaultUserInfo.java | 4 +- .../model/OIDCAuthenticationToken.java | 10 +- .../connect/model/PairwiseIdentifier.java | 6 +- .../model/PendingOIDCAuthenticationToken.java | 8 +- .../mitre/openid/connect/model/UserInfo.java | 10 +- .../connect/repository/AddressRepository.java | 2 +- .../repository/ApprovedSiteRepository.java | 10 +- .../repository/BlacklistedSiteRepository.java | 2 +- .../PairwiseIdentifierRepository.java | 6 +- .../repository/UserInfoRepository.java | 6 +- .../repository/WhitelistedSiteRepository.java | 16 +- .../connect/service/ApprovedSiteService.java | 16 +- .../service/BlacklistedSiteService.java | 2 +- .../connect/service/MITREidDataService.java | 8 +- .../service/MITREidDataServiceExtension.java | 16 +- .../service/MITREidDataServiceMaps.java | 2 +- .../connect/service/OIDCTokenService.java | 8 +- .../service/PairwiseIdentiferService.java | 6 +- .../service/ScopeClaimTranslationService.java | 2 +- .../openid/connect/service/StatsService.java | 6 +- .../connect/service/UserInfoService.java | 6 +- .../service/WhitelistedSiteService.java | 14 +- .../mitre/openid/connect/view/JWKSetView.java | 2 +- .../connect/web/UserInfoInterceptor.java | 26 +- .../main/java/org/mitre/uma/model/Claim.java | 12 +- .../uma/model/ClaimProcessingResult.java | 2 +- .../java/org/mitre/uma/model/Permission.java | 6 +- .../org/mitre/uma/model/PermissionTicket.java | 6 +- .../main/java/org/mitre/uma/model/Policy.java | 8 +- .../java/org/mitre/uma/model/ResourceSet.java | 6 +- .../uma/model/SavedRegisteredClient.java | 2 +- .../uma/repository/PermissionRepository.java | 16 +- .../uma/service/ClaimsProcessingService.java | 8 +- .../mitre/uma/service/PermissionService.java | 6 +- .../mitre/uma/service/ResourceSetService.java | 4 +- .../service/SavedRegisteredClientService.java | 4 +- .../mitre/uma/service/UmaTokenService.java | 4 +- .../main/java/org/mitre/util/JsonUtils.java | 62 +- .../main/java/org/mitre/util/jpa/JpaUtil.java | 50 +- .../AbstractPageOperationTemplateTest.java | 404 ++++---- .../org/mitre/jose/TestJWKSetKeyStore.java | 40 +- ...aultJWTEncryptionAndDecryptionService.java | 66 +- .../oauth2/model/ClientDetailsEntityTest.java | 2 +- .../oauth2/model/RegisteredClientTest.java | 2 +- .../ClientDetailsEntityJsonProcessorTest.java | 2 +- .../ConfigurationPropertiesBeanTest.java | 4 +- .../config/ServerConfigurationTest.java | 2 +- .../mitre/discovery/view/WebfingerView.java | 44 +- .../discovery/web/DiscoveryEndpoint.java | 26 +- .../AssertionOAuth2RequestFactory.java | 2 +- .../impl/DirectCopyRequestFactory.java | 11 +- .../AuthorizationPendingException.java | 6 +- .../exception/DeviceCodeExpiredException.java | 2 +- .../exception/DuplicateClientIdException.java | 2 +- .../JpaAuthenticationHolderRepository.java | 16 +- .../impl/JpaAuthorizationCodeRepository.java | 16 +- .../impl/JpaDeviceCodeRepository.java | 4 +- .../impl/JpaOAuth2TokenRepository.java | 36 +- .../impl/JpaSystemScopeRepository.java | 8 +- .../impl/BlacklistAwareRedirectResolver.java | 10 +- .../impl/DefaultDeviceCodeService.java | 49 +- .../DefaultIntrospectionResultAssembler.java | 4 +- ...DefaultOAuth2AuthorizationCodeService.java | 30 +- ...faultOAuth2ClientDetailsEntityService.java | 42 +- .../DefaultOAuth2ProviderTokenService.java | 92 +- .../impl/DefaultSystemScopeService.java | 6 +- .../oauth2/token/ChainedTokenGranter.java | 2 +- .../oauth2/token/DeviceTokenGranter.java | 30 +- .../token/JWTAssertionTokenGranter.java | 26 +- ...opeServiceAwareOAuth2RequestValidator.java | 8 +- .../org/mitre/oauth2/view/TokenApiView.java | 92 +- .../oauth2/web/AuthenticationUtilities.java | 4 +- .../java/org/mitre/oauth2/web/CorsFilter.java | 6 +- .../org/mitre/oauth2/web/DeviceEndpoint.java | 76 +- .../oauth2/web/IntrospectionEndpoint.java | 6 +- .../oauth2/web/OAuth2ExceptionHandler.java | 2 +- .../web/OAuthConfirmationController.java | 8 +- .../mitre/oauth2/web/RevocationEndpoint.java | 22 +- .../java/org/mitre/oauth2/web/ScopeAPI.java | 2 +- ...JWTBearerAssertionAuthenticationToken.java | 4 +- .../JWTBearerAuthenticationProvider.java | 14 +- ...rerClientAssertionTokenEndpointFilter.java | 4 +- .../connect/config/JsonMessageSource.java | 22 +- .../filter/AuthorizationRequestFilter.java | 16 +- .../filter/MultiUrlRequestMatcher.java | 6 +- .../repository/impl/JpaAddressRepository.java | 4 +- .../impl/JpaApprovedSiteRepository.java | 6 +- .../impl/JpaBlacklistedSiteRepository.java | 6 +- .../impl/JpaPairwiseIdentifierRepository.java | 8 +- .../impl/JpaUserInfoRepository.java | 6 +- .../impl/JpaWhitelistedSiteRepository.java | 6 +- .../request/ConnectOAuth2RequestFactory.java | 12 +- .../request/ConnectRequestParameters.java | 6 +- .../impl/DefaultApprovedSiteService.java | 6 +- .../impl/DefaultBlacklistedSiteService.java | 2 +- .../service/impl/DefaultOIDCTokenService.java | 14 +- .../DefaultScopeClaimTranslationService.java | 4 +- .../service/impl/DefaultStatsService.java | 10 +- .../service/impl/DefaultUserInfoService.java | 4 +- .../impl/DefaultWhitelistedSiteService.java | 4 +- .../service/impl/DummyResourceSetService.java | 2 +- .../InMemoryClientLogoLoadingService.java | 20 +- .../service/impl/MITREidDataService_1_0.java | 860 ++++++++--------- .../service/impl/MITREidDataService_1_1.java | 878 +++++++++--------- .../service/impl/MITREidDataService_1_2.java | 793 ++++++++-------- .../service/impl/MITREidDataService_1_3.java | 832 ++++++++--------- .../impl/MatchLoginHintsAgainstUsers.java | 2 +- .../service/impl/PassAllLoginHints.java | 2 +- .../impl/RemoveLoginHintsWithHTTP.java | 2 +- .../impl/UUIDPairwiseIdentiferService.java | 2 +- .../connect/token/ConnectTokenEnhancer.java | 21 +- .../token/TofuUserApprovalHandler.java | 21 +- .../openid/connect/util/IdTokenHashUtils.java | 8 +- .../view/AbstractClientEntityView.java | 141 ++- .../view/ClientEntityViewForAdmins.java | 6 +- .../view/ClientEntityViewForUsers.java | 6 +- .../view/ClientInformationResponseView.java | 6 +- .../openid/connect/view/HttpCodeView.java | 2 +- .../connect/view/JsonApprovedSiteView.java | 70 +- .../openid/connect/view/JsonEntityView.java | 44 +- .../openid/connect/view/JsonErrorView.java | 46 +- .../openid/connect/view/UserInfoJWTView.java | 12 +- .../openid/connect/view/UserInfoView.java | 8 +- .../openid/connect/web/ApprovedSiteAPI.java | 8 +- .../web/AuthenticationTimeStamper.java | 4 +- .../openid/connect/web/BlacklistAPI.java | 4 +- .../mitre/openid/connect/web/ClientAPI.java | 215 ++--- .../org/mitre/openid/connect/web/DataAPI.java | 61 +- .../DynamicClientRegistrationEndpoint.java | 277 +++--- ...ProtectedResourceRegistrationEndpoint.java | 10 +- .../connect/web/ServerConfigInterceptor.java | 8 +- .../mitre/openid/connect/web/StatsAPI.java | 20 +- .../openid/connect/web/UserInfoEndpoint.java | 2 +- .../openid/connect/web/WhitelistAPI.java | 4 +- .../TestBlacklistAwareRedirectResolver.java | 8 +- ...stDefaultIntrospectionResultAssembler.java | 103 +- ...faultOAuth2ClientDetailsEntityService.java | 101 +- .../impl/TestDefaultSystemScopeService.java | 2 - .../impl/TestDefaultApprovedSiteService.java | 7 +- .../service/impl/TestDefaultStatsService.java | 1 - .../impl/TestDefaultUserInfoService.java | 2 +- .../impl/TestMITREidDataService_1_0.java | 10 +- .../impl/TestMITREidDataService_1_1.java | 10 +- .../impl/TestMITREidDataService_1_2.java | 21 +- .../impl/TestMITREidDataService_1_3.java | 13 +- .../TestUUIDPairwiseIdentiferService.java | 2 +- .../connect/util/TestIdTokenHashUtils.java | 2 +- .../impl/MatchAllClaimsOnAnyPolicy.java | 2 +- .../impl/UmaDataServiceExtension_1_3.java | 508 +++++----- .../util/ExternalLoginAuthoritiesMapper.java | 2 +- .../ResourceSetEntityAbbreviatedView.java | 44 +- .../mitre/uma/view/ResourceSetEntityView.java | 44 +- .../uma/web/AuthorizationRequestEndpoint.java | 4 - .../uma/web/ClaimsCollectionEndpoint.java | 4 +- .../web/PermissionRegistrationEndpoint.java | 8 +- .../java/org/mitre/uma/web/PolicyAPI.java | 2 +- .../web/ResourceSetRegistrationEndpoint.java | 14 +- .../impl/TestDefaultPermissionService.java | 4 +- .../impl/TestDefaultResourceSetService.java | 4 +- 248 files changed, 4079 insertions(+), 4198 deletions(-) diff --git a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/IntrospectingTokenService.java b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/IntrospectingTokenService.java index 62f65c7fde..595cc4a49c 100644 --- a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/IntrospectingTokenService.java +++ b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/IntrospectingTokenService.java @@ -16,6 +16,8 @@ *******************************************************************************/ package org.mitre.oauth2.introspectingfilter; +import static org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod.SECRET_BASIC; + import java.io.IOException; import java.net.URI; import java.util.Calendar; @@ -54,8 +56,6 @@ import com.google.gson.JsonParser; import com.nimbusds.jose.util.Base64; -import static org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod.SECRET_BASIC; - /** * This ResourceServerTokenServices implementation introspects incoming tokens at a * server's introspection endpoint URL and passes an Authentication object along diff --git a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/IntrospectionAuthorityGranter.java b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/IntrospectionAuthorityGranter.java index 0117f5aca9..6d3526b5a8 100644 --- a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/IntrospectionAuthorityGranter.java +++ b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/IntrospectionAuthorityGranter.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.introspectingfilter.service; diff --git a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/IntrospectionConfigurationService.java b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/IntrospectionConfigurationService.java index 6223779f25..192d2e7a6b 100644 --- a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/IntrospectionConfigurationService.java +++ b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/IntrospectionConfigurationService.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.introspectingfilter.service; diff --git a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/JWTParsingIntrospectionConfigurationService.java b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/JWTParsingIntrospectionConfigurationService.java index 90ff0278c3..e1f04aa0e5 100644 --- a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/JWTParsingIntrospectionConfigurationService.java +++ b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/JWTParsingIntrospectionConfigurationService.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.introspectingfilter.service.impl; @@ -32,11 +32,11 @@ import com.nimbusds.jwt.JWTParser; /** - * + * * Parses the incoming accesstoken as a JWT and determines the issuer based on * the "iss" field inside the JWT. Uses the ServerConfigurationService to determine * the introspection URL for that issuer. - * + * * @author jricher * */ diff --git a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/ScopeBasedIntrospectionAuthoritiesGranter.java b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/ScopeBasedIntrospectionAuthoritiesGranter.java index 346041c332..f6fa4e9a45 100644 --- a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/ScopeBasedIntrospectionAuthoritiesGranter.java +++ b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/ScopeBasedIntrospectionAuthoritiesGranter.java @@ -34,7 +34,7 @@ * */ public class ScopeBasedIntrospectionAuthoritiesGranter implements IntrospectionAuthorityGranter { - + private List authorities = AuthorityUtils.createAuthorityList("ROLE_API"); /* (non-Javadoc) @@ -43,7 +43,7 @@ public class ScopeBasedIntrospectionAuthoritiesGranter implements IntrospectionA @Override public List getAuthorities(JsonObject introspectionResponse) { List auth = new ArrayList<>(getAuthorities()); - + if (introspectionResponse.has("scope") && introspectionResponse.get("scope").isJsonPrimitive()) { String scopeString = introspectionResponse.get("scope").getAsString(); Set scopes = OAuth2Utils.parseParameterList(scopeString); @@ -51,7 +51,7 @@ public List getAuthorities(JsonObject introspectionResponse) { auth.add(new SimpleGrantedAuthority("OAUTH_SCOPE_" + scope)); } } - + return auth; } diff --git a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/SimpleIntrospectionAuthorityGranter.java b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/SimpleIntrospectionAuthorityGranter.java index 1bb4363ea8..3b966aadc0 100644 --- a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/SimpleIntrospectionAuthorityGranter.java +++ b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/SimpleIntrospectionAuthorityGranter.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.introspectingfilter.service.impl; @@ -28,9 +28,9 @@ import com.google.gson.JsonObject; /** - * + * * Grants the same set of authorities no matter what's passed in. - * + * * @author jricher * */ diff --git a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/StaticIntrospectionConfigurationService.java b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/StaticIntrospectionConfigurationService.java index 18c8f7003e..85d2ec3f79 100644 --- a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/StaticIntrospectionConfigurationService.java +++ b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/service/impl/StaticIntrospectionConfigurationService.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.introspectingfilter.service.impl; @@ -23,10 +23,10 @@ import org.mitre.oauth2.model.RegisteredClient; /** - * + * * Always provides the (configured) IntrospectionURL and RegisteredClient regardless * of token. Useful for talking to a single, trusted authorization server. - * + * * @author jricher * */ diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/AuthorizationEndpointException.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/AuthorizationEndpointException.java index be017f4739..23b5773f5d 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/AuthorizationEndpointException.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/AuthorizationEndpointException.java @@ -7,9 +7,9 @@ public class AuthorizationEndpointException extends AuthenticationServiceExcepti private static final long serialVersionUID = 6953119789654778380L; private String error; - + private String errorDescription; - + private String errorURI; public AuthorizationEndpointException(String error, String errorDescription, String errorURI) { diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/NamedAdminAuthoritiesMapper.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/NamedAdminAuthoritiesMapper.java index 99793dfac3..b13b32200f 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/NamedAdminAuthoritiesMapper.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/NamedAdminAuthoritiesMapper.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.client; @@ -34,13 +34,13 @@ import com.nimbusds.jwt.JWTClaimsSet; /** - * + * * Simple mapper that adds ROLE_USER to the authorities map for all queries, * plus adds ROLE_ADMIN if the subject and issuer pair are found in the * configurable "admins" set. - * + * * @author jricher - * + * */ public class NamedAdminAuthoritiesMapper implements OIDCAuthoritiesMapper { diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java index 6a52b3f3c3..62b5a7027c 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java @@ -88,9 +88,9 @@ /** * OpenID Connect Authentication Filter class - * + * * @author nemonik, jricher - * + * */ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFilter { @@ -169,9 +169,9 @@ public void afterPropertiesSet() { /* * This is the main entry point for the filter. - * + * * (non-Javadoc) - * + * * @see org.springframework.security.web.authentication. * AbstractAuthenticationProcessingFilter * #attemptAuthentication(javax.servlet.http.HttpServletRequest, @@ -204,7 +204,7 @@ public Authentication attemptAuthentication(HttpServletRequest request, HttpServ /** * Initiate an Authorization request - * + * * @param request * The request from which to extract parameters and perform the * authentication @@ -270,7 +270,7 @@ protected void handleAuthorizationRequest(HttpServletRequest request, HttpServle String state = createState(session); Map options = authOptions.getOptions(serverConfig, clientConfig, request); - + // if we're using PKCE, handle the challenge here if (clientConfig.getCodeChallengeMethod() != null) { String codeVerifier = createCodeVerifier(session); @@ -287,7 +287,7 @@ protected void handleAuthorizationRequest(HttpServletRequest request, HttpServle e.printStackTrace(); } - + } } @@ -330,7 +330,7 @@ protected Authentication handleAuthorizationCodeResponse(HttpServletRequest requ form.add("grant_type", "authorization_code"); form.add("code", authorizationCode); form.setAll(authOptions.getTokenOptions(serverConfig, clientConfig, request)); - + String codeVerifier = getStoredCodeVerifier(session); if (codeVerifier != null) { form.add("code_verifier", codeVerifier); @@ -345,11 +345,11 @@ protected Authentication handleAuthorizationCodeResponse(HttpServletRequest requ if(httpClient == null) { httpClient = HttpClientBuilder.create() - .useSystemProperties() - .setDefaultRequestConfig(RequestConfig.custom() - .setSocketTimeout(httpSocketTimeout) - .build()) - .build(); + .useSystemProperties() + .setDefaultRequestConfig(RequestConfig.custom() + .setSocketTimeout(httpSocketTimeout) + .build()) + .build(); } HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient); @@ -634,7 +634,7 @@ protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOE /** * Handle Authorization Endpoint error - * + * * @param request * The request from which to extract parameters and handle the * error @@ -708,7 +708,7 @@ protected static String createState(HttpSession session) { protected static String getStoredState(HttpSession session) { return getStoredSessionString(session, STATE_SESSION_VARIABLE); } - + /** * Create a random code challenge and store it in the session * @param session @@ -719,7 +719,7 @@ protected static String createCodeVerifier(HttpSession session) { session.setAttribute(CODE_VERIFIER_SESSION_VARIABLE, challenge); return challenge; } - + /** * Retrieve the stored challenge from our session * @param session diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationProvider.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationProvider.java index de7e7fdf0e..462c194a17 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationProvider.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationProvider.java @@ -34,7 +34,7 @@ /** * @author nemonik, Justin Richer - * + * */ public class OIDCAuthenticationProvider implements AuthenticationProvider { @@ -46,7 +46,7 @@ public class OIDCAuthenticationProvider implements AuthenticationProvider { /* * (non-Javadoc) - * + * * @see org.springframework.security.authentication.AuthenticationProvider# * authenticate(org.springframework.security.core.Authentication) */ @@ -86,7 +86,7 @@ public Authentication authenticate(final Authentication authentication) throws A /** * Override this function to return a different kind of Authentication, processes the authorities differently, * or do post-processing based on the UserInfo object. - * + * * @param token * @param authorities * @param userInfo @@ -115,7 +115,7 @@ public void setAuthoritiesMapper(OIDCAuthoritiesMapper authoritiesMapper) { /* * (non-Javadoc) - * + * * @see * org.springframework.security.authentication.AuthenticationProvider#supports * (java.lang.Class) diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/StaticPrefixTargetLinkURIChecker.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/StaticPrefixTargetLinkURIChecker.java index ebf640ba59..906741d70b 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/StaticPrefixTargetLinkURIChecker.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/StaticPrefixTargetLinkURIChecker.java @@ -19,7 +19,7 @@ /** * Simple target URI checker, checks whether the string in question starts * with a configured prefix. Returns "/" if the match fails. - * + * * @author jricher * */ diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/SubjectIssuerGrantedAuthority.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/SubjectIssuerGrantedAuthority.java index e6620a0705..45b6e7e317 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/SubjectIssuerGrantedAuthority.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/SubjectIssuerGrantedAuthority.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.client; @@ -24,9 +24,9 @@ import com.google.common.base.Strings; /** - * + * * Simple authority representing a user at an issuer. - * + * * @author jricher * */ @@ -51,9 +51,9 @@ public SubjectIssuerGrantedAuthority(String subject, String issuer) { /** * Returns a string formed by concatenating the subject with the issuer, separated by _ and prepended with OIDC_ - * + * * For example, the user "bob" from issuer "http://id.example.com/" would return the authority string of: - * + * * OIDC_bob_http://id.example.com/ */ @Override diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/TargetLinkURIChecker.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/TargetLinkURIChecker.java index ba3112a072..9d688334c1 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/TargetLinkURIChecker.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/TargetLinkURIChecker.java @@ -20,7 +20,7 @@ public interface TargetLinkURIChecker { /** * Check the parameter to make sure that it's a valid deep-link into this application. - * + * * @param target * @return */ diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/UserInfoFetcher.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/UserInfoFetcher.java index ecaed19e88..faa9747784 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/UserInfoFetcher.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/UserInfoFetcher.java @@ -60,7 +60,7 @@ public class UserInfoFetcher { private static final Logger logger = LoggerFactory.getLogger(UserInfoFetcher.class); private LoadingCache cache; - + public UserInfoFetcher() { this(HttpClientBuilder.create().useSystemProperties().build()); } @@ -71,7 +71,7 @@ public UserInfoFetcher(HttpClient httpClient) { .maximumSize(100) .build(new UserInfoLoader(httpClient)); } - + public UserInfo loadUserInfo(final PendingOIDCAuthenticationToken token) { try { return cache.get(token); @@ -81,8 +81,8 @@ public UserInfo loadUserInfo(final PendingOIDCAuthenticationToken token) { } } - - + + private class UserInfoLoader extends CacheLoader { private HttpComponentsClientHttpRequestFactory factory; @@ -90,22 +90,23 @@ private class UserInfoLoader extends CacheLoader blacklist) { /** * Loader class that fetches the client information. - * + * * If a client has been registered (ie, it's known to the RegisteredClientService), then this * will fetch the client's configuration from the server. - * + * * @author jricher * */ @@ -203,12 +203,12 @@ public RegisteredClient load(ServerConfiguration serverConfig) throws Exception try { String registered = restTemplate.postForObject(serverConfig.getRegistrationEndpointUri(), entity, String.class); - + RegisteredClient client = ClientDetailsEntityJsonProcessor.parseRegistered(registered); - + // save this client for later registeredClientService.save(serverConfig.getIssuer(), client); - + return client; } catch (RestClientException rce) { throw new InvalidClientException("Error registering client with server"); @@ -227,9 +227,9 @@ public RegisteredClient load(ServerConfiguration serverConfig) throws Exception try { String registered = restTemplate.exchange(knownClient.getRegistrationClientUri(), HttpMethod.GET, entity, String.class).getBody(); // TODO: handle HTTP errors - + RegisteredClient client = ClientDetailsEntityJsonProcessor.parseRegistered(registered); - + return client; } catch (RestClientException rce) { throw new InvalidClientException("Error loading previously registered client information from server"); diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/DynamicServerConfigurationService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/DynamicServerConfigurationService.java index 02646f7ba4..5d80cce51b 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/DynamicServerConfigurationService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/DynamicServerConfigurationService.java @@ -15,10 +15,17 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.client.service.impl; +import static org.mitre.util.JsonUtils.getAsBoolean; +import static org.mitre.util.JsonUtils.getAsEncryptionMethodList; +import static org.mitre.util.JsonUtils.getAsJweAlgorithmList; +import static org.mitre.util.JsonUtils.getAsJwsAlgorithmList; +import static org.mitre.util.JsonUtils.getAsString; +import static org.mitre.util.JsonUtils.getAsStringList; + import java.util.HashSet; import java.util.Set; import java.util.concurrent.ExecutionException; @@ -41,17 +48,10 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import static org.mitre.util.JsonUtils.getAsBoolean; -import static org.mitre.util.JsonUtils.getAsEncryptionMethodList; -import static org.mitre.util.JsonUtils.getAsJweAlgorithmList; -import static org.mitre.util.JsonUtils.getAsJwsAlgorithmList; -import static org.mitre.util.JsonUtils.getAsString; -import static org.mitre.util.JsonUtils.getAsStringList; - /** - * + * * Dynamically fetches OpenID Connect server configurations based on the issuer. Caches the server configurations. - * + * * @author jricher * */ @@ -133,9 +133,9 @@ private class OpenIDConnectServiceConfigurationFetcher extends CacheLoader() { - @Override - public JsonElement serialize(RegisteredClient src, Type typeOfSrc, JsonSerializationContext context) { - return ClientDetailsEntityJsonProcessor.serialize(src); - } - }) - .registerTypeAdapter(RegisteredClient.class, new JsonDeserializer() { - @Override - public RegisteredClient deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - return ClientDetailsEntityJsonProcessor.parseRegistered(json); - } - }) - .setPrettyPrinting() - .create(); + .registerTypeAdapter(RegisteredClient.class, new JsonSerializer() { + @Override + public JsonElement serialize(RegisteredClient src, Type typeOfSrc, JsonSerializationContext context) { + return ClientDetailsEntityJsonProcessor.serialize(src); + } + }) + .registerTypeAdapter(RegisteredClient.class, new JsonDeserializer() { + @Override + public RegisteredClient deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + return ClientDetailsEntityJsonProcessor.parseRegistered(json); + } + }) + .setPrettyPrinting() + .create(); private File file; diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/PlainAuthRequestUrlBuilder.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/PlainAuthRequestUrlBuilder.java index 90d3ad9635..d7d4916024 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/PlainAuthRequestUrlBuilder.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/PlainAuthRequestUrlBuilder.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.client.service.impl; @@ -33,9 +33,9 @@ import com.google.common.base.Strings; /** - * + * * Builds an auth request redirect URI with normal query parameters. - * + * * @author jricher * */ diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/SignedAuthRequestUrlBuilder.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/SignedAuthRequestUrlBuilder.java index 5051f2cd62..1a8c855ea4 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/SignedAuthRequestUrlBuilder.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/SignedAuthRequestUrlBuilder.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.client.service.impl; diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticAuthRequestOptionsService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticAuthRequestOptionsService.java index 7b18c6a0ae..6b91b4d60f 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticAuthRequestOptionsService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticAuthRequestOptionsService.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.client.service.impl; @@ -29,9 +29,9 @@ import org.mitre.openid.connect.config.ServerConfiguration; /** - * + * * Always returns the same set of options. - * + * * @author jricher * */ diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticClientConfigurationService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticClientConfigurationService.java index 89be2391ab..f11bb3ccde 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticClientConfigurationService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticClientConfigurationService.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.client.service.impl; @@ -29,9 +29,9 @@ /** * Client configuration service that holds a static map from issuer URL to a ClientDetails object to use at that issuer. - * + * * Designed to be configured as a bean. - * + * * @author jricher * */ @@ -56,7 +56,7 @@ public void setClients(Map clients) { /** * Get the client configured for this issuer - * + * * @see org.mitre.openid.connect.client.service.ClientConfigurationService#getClientConfiguration(java.lang.String) */ @Override diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticServerConfigurationService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticServerConfigurationService.java index a3432cbbae..43e3964308 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticServerConfigurationService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticServerConfigurationService.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.client.service.impl; @@ -28,7 +28,7 @@ /** * Statically configured server configuration service that maps issuer URLs to server configurations to use at that issuer. - * + * * @author jricher * */ diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticSingleIssuerService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticSingleIssuerService.java index fbb88efccc..eaf04354e5 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticSingleIssuerService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticSingleIssuerService.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.client.service.impl; @@ -51,7 +51,7 @@ public void setIssuer(String issuer) { /** * Always returns the configured issuer URL - * + * * @see org.mitre.openid.connect.client.service.IssuerService#getIssuer(javax.servlet.http.HttpServletRequest) */ @Override diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/ThirdPartyIssuerService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/ThirdPartyIssuerService.java index 552a882d1b..412f49ab05 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/ThirdPartyIssuerService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/ThirdPartyIssuerService.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.client.service.impl; @@ -34,9 +34,9 @@ import com.google.common.base.Strings; /** - * + * * Determines the issuer using an account chooser or other third-party-initiated login - * + * * @author jricher * */ diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/WebfingerIssuerService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/WebfingerIssuerService.java index 41ab8b9def..33df5aeb5a 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/WebfingerIssuerService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/WebfingerIssuerService.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.client.service.impl; @@ -74,7 +74,7 @@ public LoadingResult(String loginHint, String issuer) { this.issuer = issuer; } } - + private Set whitelist = new HashSet<>(); private Set blacklist = new HashSet<>(); @@ -118,7 +118,7 @@ public IssuerServiceResponse getIssuer(HttpServletRequest request) { if (blacklist.contains(lr.issuer)) { throw new AuthenticationServiceException("Issuer was in blacklist: " + lr.issuer); } - + return new IssuerServiceResponse(lr.issuer, lr.loginHint, request.getParameter("target_link_uri")); } catch (UncheckedExecutionException | ExecutionException e) { logger.warn("Issue fetching issuer for user input: " + identifier + ": " + e.getMessage()); @@ -218,7 +218,7 @@ private class WebfingerIssuerFetcher extends CacheLoader public LoadingResult load(String identifier) throws Exception { UriComponents key = WebfingerURLNormalizer.normalizeResource(identifier); - + RestTemplate restTemplate = new RestTemplate(httpFactory); // construct the URL to go to @@ -268,7 +268,7 @@ public LoadingResult load(String identifier) throws Exception { // we found the issuer, return it String href = linkObj.get("href").getAsString(); - + if (identifier.equals(href) || identifier.startsWith("http")) { // try to avoid sending a URL as the login hint diff --git a/openid-connect-client/src/test/java/org/mitre/oauth2/introspectingfilter/service/impl/TestScopeBasedIntrospectionAuthoritiesGranter.java b/openid-connect-client/src/test/java/org/mitre/oauth2/introspectingfilter/service/impl/TestScopeBasedIntrospectionAuthoritiesGranter.java index 0fcc3884f1..d122ed85c8 100644 --- a/openid-connect-client/src/test/java/org/mitre/oauth2/introspectingfilter/service/impl/TestScopeBasedIntrospectionAuthoritiesGranter.java +++ b/openid-connect-client/src/test/java/org/mitre/oauth2/introspectingfilter/service/impl/TestScopeBasedIntrospectionAuthoritiesGranter.java @@ -38,7 +38,7 @@ public class TestScopeBasedIntrospectionAuthoritiesGranter { private JsonObject introspectionResponse; private ScopeBasedIntrospectionAuthoritiesGranter granter = new ScopeBasedIntrospectionAuthoritiesGranter(); - + /** * @throws java.lang.Exception */ @@ -53,16 +53,16 @@ public void setUp() throws Exception { @Test public void testGetAuthoritiesJsonObject_withScopes() { introspectionResponse.addProperty("scope", "foo bar baz batman"); - + List expected = new ArrayList<>(); expected.add(new SimpleGrantedAuthority("ROLE_API")); expected.add(new SimpleGrantedAuthority("OAUTH_SCOPE_foo")); expected.add(new SimpleGrantedAuthority("OAUTH_SCOPE_bar")); expected.add(new SimpleGrantedAuthority("OAUTH_SCOPE_baz")); expected.add(new SimpleGrantedAuthority("OAUTH_SCOPE_batman")); - + List authorities = granter.getAuthorities(introspectionResponse); - + assertTrue(authorities.containsAll(expected)); assertTrue(expected.containsAll(authorities)); } @@ -72,12 +72,12 @@ public void testGetAuthoritiesJsonObject_withScopes() { */ @Test public void testGetAuthoritiesJsonObject_withoutScopes() { - + List expected = new ArrayList<>(); expected.add(new SimpleGrantedAuthority("ROLE_API")); - + List authorities = granter.getAuthorities(introspectionResponse); - + assertTrue(authorities.containsAll(expected)); assertTrue(expected.containsAll(authorities)); } diff --git a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/TestOIDCAuthenticationFilter.java b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/TestOIDCAuthenticationFilter.java index 2918e11896..46ae7397f1 100644 --- a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/TestOIDCAuthenticationFilter.java +++ b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/TestOIDCAuthenticationFilter.java @@ -1,11 +1,5 @@ package org.mitre.openid.connect.client; -import static org.hamcrest.CoreMatchers.instanceOf; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -13,13 +7,21 @@ import org.mockito.Mockito; import org.springframework.security.authentication.AuthenticationServiceException; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; + +import static org.mockito.Mockito.mock; + +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + public class TestOIDCAuthenticationFilter { private OIDCAuthenticationFilter filter = new OIDCAuthenticationFilter(); - + @Test public void attemptAuthentication_error() throws Exception { - + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); Mockito.when(request.getParameter("error")).thenReturn("Error"); Mockito.when(request.getParameter("error_description")).thenReturn("Description"); @@ -27,13 +29,13 @@ public void attemptAuthentication_error() throws Exception { try { filter.attemptAuthentication(request, mock(HttpServletResponse.class)); - + fail("AuthorizationEndpointException expected."); } catch (AuthorizationEndpointException exception) { assertThat(exception.getMessage(), is("Error from Authorization Endpoint: Error Description http://example.com")); - + assertThat(exception.getError(), is("Error")); assertThat(exception.getErrorDescription(), is("Description")); assertThat(exception.getErrorURI(), is("http://example.com")); diff --git a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestSignedAuthRequestUrlBuilder.java b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestSignedAuthRequestUrlBuilder.java index 8e2eea4210..8ba354dc7d 100644 --- a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestSignedAuthRequestUrlBuilder.java +++ b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestSignedAuthRequestUrlBuilder.java @@ -52,7 +52,7 @@ /** * @author wkim - * + * */ public class TestSignedAuthRequestUrlBuilder { diff --git a/openid-connect-common/src/main/java/org/mitre/data/AbstractPageOperationTemplate.java b/openid-connect-common/src/main/java/org/mitre/data/AbstractPageOperationTemplate.java index 3494307df3..7911f2f029 100644 --- a/openid-connect-common/src/main/java/org/mitre/data/AbstractPageOperationTemplate.java +++ b/openid-connect-common/src/main/java/org/mitre/data/AbstractPageOperationTemplate.java @@ -1,12 +1,12 @@ package org.mitre.data; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.Collection; import java.util.HashSet; import java.util.Set; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Abstract class for performing an operation on a potentially large * number of items by paging through the items in discreet chunks. @@ -16,162 +16,162 @@ */ public abstract class AbstractPageOperationTemplate { - private static final Logger logger = LoggerFactory.getLogger(AbstractPageOperationTemplate.class); - - private static int DEFAULT_MAX_PAGES = 1000; - private static long DEFAULT_MAX_TIME_MILLIS = 600000L; //10 Minutes - - /** - * int specifying the maximum number of - * pages which should be fetched before - * execution should terminate - */ - private int maxPages; - - /** - * long specifying the maximum execution time - * in milliseconds - */ - private long maxTime; - - /** - * boolean specifying whether or not Exceptions - * incurred performing the operation should be - * swallowed during execution default true. - */ - private boolean swallowExceptions = true; - - /** - * String that is used for logging in final tallies. - */ - private String operationName = ""; - - - /** - * default constructor which sets the value of - * maxPages and maxTime to DEFAULT_MAX_PAGES and - * DEFAULT_MAX_TIME_MILLIS respectively - */ - public AbstractPageOperationTemplate(String operationName){ - this(DEFAULT_MAX_PAGES, DEFAULT_MAX_TIME_MILLIS, operationName); - } - - /** - * Instantiates a new AbstractPageOperationTemplate with the - * given maxPages and maxTime - * - * @param maxPages the maximum number of pages to fetch. - * @param maxTime the maximum execution time. - */ - public AbstractPageOperationTemplate(int maxPages, long maxTime, String operationName){ - this.maxPages = maxPages; - this.maxTime = maxTime; - this.operationName = operationName; - } - - /** - * Execute the operation on each member of a page of results - * retrieved through the fetch method. the method will execute - * until either the maxPages or maxTime limit is reached or until - * the fetch method returns no more results. Exceptions thrown - * performing the operation on the item will be swallowed if the - * swallowException (default true) field is set true. - */ - public void execute(){ - logger.debug("[" + getOperationName() + "] Starting execution of paged operation. maximum time: " + maxTime + ", maximum pages: " + maxPages); - - long startTime = System.currentTimeMillis(); - long executionTime = 0; - int i = 0; - - int exceptionsSwallowedCount = 0; - int operationsCompleted = 0; - Set exceptionsSwallowedClasses = new HashSet(); - - - while (i< maxPages && executionTime < maxTime){ - Collection page = fetchPage(); - if(page == null || page.size() == 0){ - break; - } - - for (T item : page) { - try { - doOperation(item); - operationsCompleted++; - } catch (Exception e){ - if(swallowExceptions){ - exceptionsSwallowedCount++; - exceptionsSwallowedClasses.add(e.getClass().getName()); - logger.debug("Swallowing exception " + e.getMessage(), e); - } else { - logger.debug("Rethrowing exception " + e.getMessage()); - throw e; - } - } - } - - i++; - executionTime = System.currentTimeMillis() - startTime; - } - - finalReport(operationsCompleted, exceptionsSwallowedCount, exceptionsSwallowedClasses); - } - - - - /** - * method responsible for fetching - * a page of items. - * - * @return the collection of items - */ - public abstract Collection fetchPage(); - - /** - * method responsible for performing desired - * operation on a fetched page item. - * - * @param item the item - */ - protected abstract void doOperation(T item); - - /** - * Method responsible for final report of progress. - * @return - */ - protected void finalReport(int operationsCompleted, int exceptionsSwallowedCount, Set exceptionsSwallowedClasses) { - if (operationsCompleted > 0 || exceptionsSwallowedCount > 0) { - logger.info("[" + getOperationName() + "] Paged operation run: completed " + operationsCompleted + "; swallowed " + exceptionsSwallowedCount + " exceptions"); - } - for(String className: exceptionsSwallowedClasses) { - logger.warn("[" + getOperationName() + "] Paged operation swallowed at least one exception of type " + className); - } - } - - public int getMaxPages() { - return maxPages; - } - - public void setMaxPages(int maxPages) { - this.maxPages = maxPages; - } - - public long getMaxTime() { - return maxTime; - } - - public void setMaxTime(long maxTime) { - this.maxTime = maxTime; - } - - public boolean isSwallowExceptions() { - return swallowExceptions; - } - - public void setSwallowExceptions(boolean swallowExceptions) { - this.swallowExceptions = swallowExceptions; - } + private static final Logger logger = LoggerFactory.getLogger(AbstractPageOperationTemplate.class); + + private static int DEFAULT_MAX_PAGES = 1000; + private static long DEFAULT_MAX_TIME_MILLIS = 600000L; //10 Minutes + + /** + * int specifying the maximum number of + * pages which should be fetched before + * execution should terminate + */ + private int maxPages; + + /** + * long specifying the maximum execution time + * in milliseconds + */ + private long maxTime; + + /** + * boolean specifying whether or not Exceptions + * incurred performing the operation should be + * swallowed during execution default true. + */ + private boolean swallowExceptions = true; + + /** + * String that is used for logging in final tallies. + */ + private String operationName = ""; + + + /** + * default constructor which sets the value of + * maxPages and maxTime to DEFAULT_MAX_PAGES and + * DEFAULT_MAX_TIME_MILLIS respectively + */ + public AbstractPageOperationTemplate(String operationName){ + this(DEFAULT_MAX_PAGES, DEFAULT_MAX_TIME_MILLIS, operationName); + } + + /** + * Instantiates a new AbstractPageOperationTemplate with the + * given maxPages and maxTime + * + * @param maxPages the maximum number of pages to fetch. + * @param maxTime the maximum execution time. + */ + public AbstractPageOperationTemplate(int maxPages, long maxTime, String operationName){ + this.maxPages = maxPages; + this.maxTime = maxTime; + this.operationName = operationName; + } + + /** + * Execute the operation on each member of a page of results + * retrieved through the fetch method. the method will execute + * until either the maxPages or maxTime limit is reached or until + * the fetch method returns no more results. Exceptions thrown + * performing the operation on the item will be swallowed if the + * swallowException (default true) field is set true. + */ + public void execute(){ + logger.debug("[" + getOperationName() + "] Starting execution of paged operation. maximum time: " + maxTime + ", maximum pages: " + maxPages); + + long startTime = System.currentTimeMillis(); + long executionTime = 0; + int i = 0; + + int exceptionsSwallowedCount = 0; + int operationsCompleted = 0; + Set exceptionsSwallowedClasses = new HashSet(); + + + while (i< maxPages && executionTime < maxTime){ + Collection page = fetchPage(); + if(page == null || page.size() == 0){ + break; + } + + for (T item : page) { + try { + doOperation(item); + operationsCompleted++; + } catch (Exception e){ + if(swallowExceptions){ + exceptionsSwallowedCount++; + exceptionsSwallowedClasses.add(e.getClass().getName()); + logger.debug("Swallowing exception " + e.getMessage(), e); + } else { + logger.debug("Rethrowing exception " + e.getMessage()); + throw e; + } + } + } + + i++; + executionTime = System.currentTimeMillis() - startTime; + } + + finalReport(operationsCompleted, exceptionsSwallowedCount, exceptionsSwallowedClasses); + } + + + + /** + * method responsible for fetching + * a page of items. + * + * @return the collection of items + */ + public abstract Collection fetchPage(); + + /** + * method responsible for performing desired + * operation on a fetched page item. + * + * @param item the item + */ + protected abstract void doOperation(T item); + + /** + * Method responsible for final report of progress. + * @return + */ + protected void finalReport(int operationsCompleted, int exceptionsSwallowedCount, Set exceptionsSwallowedClasses) { + if (operationsCompleted > 0 || exceptionsSwallowedCount > 0) { + logger.info("[" + getOperationName() + "] Paged operation run: completed " + operationsCompleted + "; swallowed " + exceptionsSwallowedCount + " exceptions"); + } + for(String className: exceptionsSwallowedClasses) { + logger.warn("[" + getOperationName() + "] Paged operation swallowed at least one exception of type " + className); + } + } + + public int getMaxPages() { + return maxPages; + } + + public void setMaxPages(int maxPages) { + this.maxPages = maxPages; + } + + public long getMaxTime() { + return maxTime; + } + + public void setMaxTime(long maxTime) { + this.maxTime = maxTime; + } + + public boolean isSwallowExceptions() { + return swallowExceptions; + } + + public void setSwallowExceptions(boolean swallowExceptions) { + this.swallowExceptions = swallowExceptions; + } /** diff --git a/openid-connect-common/src/main/java/org/mitre/data/DefaultPageCriteria.java b/openid-connect-common/src/main/java/org/mitre/data/DefaultPageCriteria.java index fc559c5e4d..5b0f659bb2 100644 --- a/openid-connect-common/src/main/java/org/mitre/data/DefaultPageCriteria.java +++ b/openid-connect-common/src/main/java/org/mitre/data/DefaultPageCriteria.java @@ -8,28 +8,28 @@ */ public class DefaultPageCriteria implements PageCriteria { - private static final int DEFAULT_PAGE_NUMBER = 0; - private static final int DEFAULT_PAGE_SIZE = 100; + private static final int DEFAULT_PAGE_NUMBER = 0; + private static final int DEFAULT_PAGE_SIZE = 100; - private int pageNumber; - private int pageSize; + private int pageNumber; + private int pageSize; - public DefaultPageCriteria(){ - this(DEFAULT_PAGE_NUMBER, DEFAULT_PAGE_SIZE); - } + public DefaultPageCriteria(){ + this(DEFAULT_PAGE_NUMBER, DEFAULT_PAGE_SIZE); + } - public DefaultPageCriteria(int pageNumber, int pageSize) { - this.pageNumber = pageNumber; - this.pageSize = pageSize; - } + public DefaultPageCriteria(int pageNumber, int pageSize) { + this.pageNumber = pageNumber; + this.pageSize = pageSize; + } - @Override - public int getPageNumber() { - return pageNumber; - } + @Override + public int getPageNumber() { + return pageNumber; + } - @Override - public int getPageSize() { - return pageSize; - } + @Override + public int getPageSize() { + return pageSize; + } } diff --git a/openid-connect-common/src/main/java/org/mitre/data/PageCriteria.java b/openid-connect-common/src/main/java/org/mitre/data/PageCriteria.java index f9f57562f2..0c462434ab 100644 --- a/openid-connect-common/src/main/java/org/mitre/data/PageCriteria.java +++ b/openid-connect-common/src/main/java/org/mitre/data/PageCriteria.java @@ -8,6 +8,6 @@ */ public interface PageCriteria { - public int getPageNumber(); - public int getPageSize(); + public int getPageNumber(); + public int getPageSize(); } diff --git a/openid-connect-common/src/main/java/org/mitre/discovery/util/WebfingerURLNormalizer.java b/openid-connect-common/src/main/java/org/mitre/discovery/util/WebfingerURLNormalizer.java index 0fa0d427c6..f7c61d1a4d 100644 --- a/openid-connect-common/src/main/java/org/mitre/discovery/util/WebfingerURLNormalizer.java +++ b/openid-connect-common/src/main/java/org/mitre/discovery/util/WebfingerURLNormalizer.java @@ -29,7 +29,7 @@ /** * Provides utility methods for normalizing and parsing URIs for use with Webfinger Discovery. - * + * * @author wkim * */ diff --git a/openid-connect-common/src/main/java/org/mitre/jose/keystore/JWKSetKeyStore.java b/openid-connect-common/src/main/java/org/mitre/jose/keystore/JWKSetKeyStore.java index d1eaedc9c3..c6713a6cf0 100644 --- a/openid-connect-common/src/main/java/org/mitre/jose/keystore/JWKSetKeyStore.java +++ b/openid-connect-common/src/main/java/org/mitre/jose/keystore/JWKSetKeyStore.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.jose.keystore; diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/assertion/AssertionValidator.java b/openid-connect-common/src/main/java/org/mitre/jwt/assertion/AssertionValidator.java index bf1d2e2fac..19426d05dd 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/assertion/AssertionValidator.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/assertion/AssertionValidator.java @@ -26,5 +26,5 @@ public interface AssertionValidator { public boolean isValid(JWT assertion); - + } diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/assertion/impl/NullAssertionValidator.java b/openid-connect-common/src/main/java/org/mitre/jwt/assertion/impl/NullAssertionValidator.java index 73bb6504e8..1307552a38 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/assertion/impl/NullAssertionValidator.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/assertion/impl/NullAssertionValidator.java @@ -23,7 +23,7 @@ /** * Reject all assertions passed in. - * + * * @author jricher * */ diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/assertion/impl/SelfAssertionValidator.java b/openid-connect-common/src/main/java/org/mitre/jwt/assertion/impl/SelfAssertionValidator.java index 458ccb30c2..cd169c5093 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/assertion/impl/SelfAssertionValidator.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/assertion/impl/SelfAssertionValidator.java @@ -33,7 +33,7 @@ /** * Validates all assertions generated by this server - * + * * @author jricher * */ @@ -43,17 +43,17 @@ public class SelfAssertionValidator implements AssertionValidator { @Autowired private ConfigurationPropertiesBean config; - + @Autowired private JWTSigningAndValidationService jwtService; - + @Override public boolean isValid(JWT assertion) { if (!(assertion instanceof SignedJWT)) { // unsigned assertion return false; } - + JWTClaimsSet claims; try { claims = assertion.getJWTClaimsSet(); @@ -61,17 +61,17 @@ public boolean isValid(JWT assertion) { logger.debug("Invalid assertion claims"); return false; } - + if (Strings.isNullOrEmpty(claims.getIssuer())) { logger.debug("No issuer for assertion, rejecting"); return false; } - + if (claims.getIssuer().equals(config.getIssuer())) { logger.debug("Issuer is not the same as this server, rejecting"); return false; } - + if (jwtService.validateSignature((SignedJWT) assertion)) { return true; } else { diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/assertion/impl/WhitelistedIssuerAssertionValidator.java b/openid-connect-common/src/main/java/org/mitre/jwt/assertion/impl/WhitelistedIssuerAssertionValidator.java index a87d86b94e..1c46cbce89 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/assertion/impl/WhitelistedIssuerAssertionValidator.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/assertion/impl/WhitelistedIssuerAssertionValidator.java @@ -41,12 +41,12 @@ public class WhitelistedIssuerAssertionValidator implements AssertionValidator { private static Logger logger = LoggerFactory.getLogger(WhitelistedIssuerAssertionValidator.class); - + /** * Map of issuer -> JWKSetUri */ private Map whitelist = new HashMap<>(); - + /** * @return the whitelist */ @@ -63,15 +63,15 @@ public void setWhitelist(Map whitelist) { @Autowired private JWKSetCacheService jwkCache; - + @Override public boolean isValid(JWT assertion) { - + if (!(assertion instanceof SignedJWT)) { // unsigned assertion return false; } - + JWTClaimsSet claims; try { claims = assertion.getJWTClaimsSet(); @@ -79,21 +79,21 @@ public boolean isValid(JWT assertion) { logger.debug("Invalid assertion claims"); return false; } - + if (Strings.isNullOrEmpty(claims.getIssuer())) { logger.debug("No issuer for assertion, rejecting"); return false; } - + if (!whitelist.containsKey(claims.getIssuer())) { logger.debug("Issuer is not in whitelist, rejecting"); return false; } - + String jwksUri = whitelist.get(claims.getIssuer()); - + JWTSigningAndValidationService validator = jwkCache.getValidator(jwksUri); - + if (validator.validateSignature((SignedJWT) assertion)) { return true; } else { diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/encryption/service/impl/DefaultJWTEncryptionAndDecryptionService.java b/openid-connect-common/src/main/java/org/mitre/jwt/encryption/service/impl/DefaultJWTEncryptionAndDecryptionService.java index c7fbf55dc4..bda8dea5a8 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/encryption/service/impl/DefaultJWTEncryptionAndDecryptionService.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/encryption/service/impl/DefaultJWTEncryptionAndDecryptionService.java @@ -45,7 +45,6 @@ import com.nimbusds.jose.crypto.RSADecrypter; import com.nimbusds.jose.crypto.RSAEncrypter; import com.nimbusds.jose.crypto.bc.BouncyCastleProviderSingleton; -import com.nimbusds.jose.jca.JCAContext; import com.nimbusds.jose.jwk.ECKey; import com.nimbusds.jose.jwk.JWK; import com.nimbusds.jose.jwk.OctetSequenceKey; @@ -80,7 +79,7 @@ public class DefaultJWTEncryptionAndDecryptionService implements JWTEncryptionAn /** * Build this service based on the keys given. All public keys will be used to make encrypters, * all private keys will be used to make decrypters. - * + * * @param keys * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException @@ -94,7 +93,7 @@ public DefaultJWTEncryptionAndDecryptionService(Map keys) throws No /** * Build this service based on the given keystore. All keys must have a key * id ({@code kid}) field in order to be used. - * + * * @param keyStore * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException @@ -240,13 +239,13 @@ private void buildEncryptersAndDecrypters() throws NoSuchAlgorithmException, Inv logger.warn("No private key for key #" + jwk.getKeyID()); } } else if (jwk instanceof ECKey) { - + // build EC Encrypters and decrypters - + ECDHEncrypter encrypter = new ECDHEncrypter((ECKey) jwk); encrypter.getJCAContext().setProvider(BouncyCastleProviderSingleton.getInstance()); encrypters.put(id, encrypter); - + if (jwk.isPrivate()) { // we can decrypt too ECDHDecrypter decrypter = new ECDHDecrypter((ECKey) jwk); decrypter.getJCAContext().setProvider(BouncyCastleProviderSingleton.getInstance()); diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/JWTSigningAndValidationService.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/JWTSigningAndValidationService.java index 359ce329ef..7a0f0514e2 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/JWTSigningAndValidationService.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/JWTSigningAndValidationService.java @@ -34,7 +34,7 @@ public interface JWTSigningAndValidationService { /** * Checks the signature of the given JWT against all configured signers, * returns true if at least one of the signers validates it. - * + * * @param jwtString * the string representation of the JWT as sent on the wire * @return true if the signature is valid, false if not @@ -45,7 +45,7 @@ public interface JWTSigningAndValidationService { /** * Called to sign a jwt in place for a client that hasn't registered a preferred signing algorithm. * Use the default algorithm to sign. - * + * * @param jwt the jwt to sign * @return the signed jwt * @throws NoSuchAlgorithmException @@ -67,7 +67,7 @@ public interface JWTSigningAndValidationService { /** * Sign a jwt using the selected algorithm. The algorithm is selected using the String parameter values specified * in the JWT spec, section 6. I.E., "HS256" means HMAC with SHA-256 and corresponds to our HmacSigner class. - * + * * @param jwt the jwt to sign * @param alg the name of the algorithm to use, as specified in JWS s.6 * @return the signed jwt diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/ClientKeyCacheService.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/ClientKeyCacheService.java index 0f565509bf..6fd0bd60b7 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/ClientKeyCacheService.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/ClientKeyCacheService.java @@ -39,10 +39,10 @@ import com.nimbusds.jose.jwk.JWKSet; /** - * + * * Takes in a client and returns the appropriate validator or encrypter for * that client's registered key types. - * + * * @author jricher * */ diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DefaultJWTSigningAndValidationService.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DefaultJWTSigningAndValidationService.java index 702037f19a..caab7a804c 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DefaultJWTSigningAndValidationService.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DefaultJWTSigningAndValidationService.java @@ -17,8 +17,6 @@ package org.mitre.jwt.signer.service.impl; import java.security.NoSuchAlgorithmException; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.ECPublicKey; import java.security.spec.InvalidKeySpecException; import java.util.Collection; import java.util.HashMap; @@ -72,10 +70,10 @@ public class DefaultJWTSigningAndValidationService implements JWTSigningAndValid /** * Build this service based on the keys given. All public keys will be used * to make verifiers, all private keys will be used to make signers. - * + * * @param keys * A map of key identifier to key - * + * * @throws InvalidKeySpecException * If the keys in the JWKs are not valid * @throws NoSuchAlgorithmException @@ -89,10 +87,10 @@ public DefaultJWTSigningAndValidationService(Map keys) throws NoSuc /** * Build this service based on the given keystore. All keys must have a key * id ({@code kid}) field in order to be used. - * + * * @param keyStore * the keystore to load all keys from - * + * * @throws InvalidKeySpecException * If the keys in the JWKs are not valid * @throws NoSuchAlgorithmException @@ -165,37 +163,37 @@ private void buildSignersAndVerifiers() throws NoSuchAlgorithmException, Invalid try { if (jwk instanceof RSAKey) { // build RSA signers & verifiers - + if (jwk.isPrivate()) { // only add the signer if there's a private key RSASSASigner signer = new RSASSASigner((RSAKey) jwk); signers.put(id, signer); } - + RSASSAVerifier verifier = new RSASSAVerifier((RSAKey) jwk); verifiers.put(id, verifier); - + } else if (jwk instanceof ECKey) { // build EC signers & verifiers - + if (jwk.isPrivate()) { ECDSASigner signer = new ECDSASigner((ECKey) jwk); signers.put(id, signer); } - + ECDSAVerifier verifier = new ECDSAVerifier((ECKey) jwk); verifiers.put(id, verifier); - + } else if (jwk instanceof OctetSequenceKey) { // build HMAC signers & verifiers - + if (jwk.isPrivate()) { // technically redundant check because all HMAC keys are private MACSigner signer = new MACSigner((OctetSequenceKey) jwk); signers.put(id, signer); } - + MACVerifier verifier = new MACVerifier((OctetSequenceKey) jwk); verifiers.put(id, verifier); - + } else { logger.warn("Unknown key type: " + jwk); } diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/JWKSetCacheService.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/JWKSetCacheService.java index c6ac76d30f..5528045bbb 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/JWKSetCacheService.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/JWKSetCacheService.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.jwt.signer.service.impl; @@ -43,12 +43,12 @@ import com.nimbusds.jose.jwk.JWKSet; /** - * + * * Creates a caching map of JOSE signers/validators and encrypters/decryptors * keyed on the JWK Set URI. Dynamically loads JWK Sets to create the services. - * + * * @author jricher - * + * */ @Service public class JWKSetCacheService { @@ -150,11 +150,11 @@ public JWTEncryptionAndDecryptionService load(String key) throws Exception { try { String jsonString = restTemplate.getForObject(key, String.class); JWKSet jwkSet = JWKSet.parse(jsonString); - + JWKSetKeyStore keyStore = new JWKSetKeyStore(jwkSet); - + JWTEncryptionAndDecryptionService service = new DefaultJWTEncryptionAndDecryptionService(keyStore); - + return service; } catch (JsonParseException | RestClientException e) { throw new IllegalArgumentException("Unable to load JWK Set"); diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/SymmetricKeyJWTValidatorCacheService.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/SymmetricKeyJWTValidatorCacheService.java index c9196a58b1..f90a732861 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/SymmetricKeyJWTValidatorCacheService.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/SymmetricKeyJWTValidatorCacheService.java @@ -41,7 +41,7 @@ /** * Creates and caches symmetrical validators for clients based on client secrets. - * + * * @author jricher * */ @@ -66,7 +66,7 @@ public SymmetricKeyJWTValidatorCacheService() { /** * Create a symmetric signing and validation service for the given client - * + * * @param client * @return */ diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/AuthorizationCodeEntity.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/AuthorizationCodeEntity.java index 38ac7f3f56..987cab73ed 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/AuthorizationCodeEntity.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/AuthorizationCodeEntity.java @@ -33,7 +33,7 @@ /** * Entity class for authorization codes - * + * * @author aanganes * */ @@ -67,7 +67,7 @@ public AuthorizationCodeEntity() { /** * Create a new AuthorizationCodeEntity with the given code and AuthorizationRequestHolder. - * + * * @param code the authorization code * @param authRequest the AuthoriztionRequestHolder associated with the original code request */ diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/ClientDetailsEntity.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/ClientDetailsEntity.java index 2a4a0ea80f..914921341e 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/ClientDetailsEntity.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/ClientDetailsEntity.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.model; @@ -57,7 +57,6 @@ import org.springframework.security.core.GrantedAuthority; import org.springframework.security.oauth2.provider.ClientDetails; -import com.nimbusds.jose.Algorithm; import com.nimbusds.jose.EncryptionMethod; import com.nimbusds.jose.JWEAlgorithm; import com.nimbusds.jose.JWSAlgorithm; @@ -66,7 +65,7 @@ /** * @author jricher - * + * */ @Entity @Table(name = "client_details") @@ -151,10 +150,10 @@ public class ClientDetailsEntity implements ClientDetails { /** fields for UMA */ private Set claimsRedirectUris; - + /** Software statement **/ private JWT softwareStatement; - + /** PKCE **/ private PKCEAlgorithm codeChallengeMethod; @@ -239,7 +238,7 @@ public static SubjectType getByValue(String value) { return lookup.get(value); } } - + /** * Create a blank ClientDetailsEntity */ @@ -267,7 +266,7 @@ public Long getId() { } /** - * + * * @param id the id to set */ public void setId(Long id) { @@ -314,7 +313,7 @@ public void setReuseRefreshToken(boolean reuseRefreshToken) { /** * Number of seconds ID token is valid for. MUST be a positive integer, can not be null. - * + * * @return the idTokenValiditySeconds */ @Basic @@ -367,7 +366,7 @@ public void setAllowIntrospection(boolean allowIntrospection) { } /** - * + * */ @Override @Transient @@ -580,9 +579,9 @@ public void setResourceIds(Set resourceIds) { /** * This library does not make use of this field, so it is not * stored using our persistence layer. - * + * * However, it's somehow required by SECOUATH. - * + * * @return an empty map */ @Override diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/DeviceCode.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/DeviceCode.java index a886729c30..417f6efb7c 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/DeviceCode.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/DeviceCode.java @@ -54,11 +54,11 @@ public class DeviceCode { public static final String QUERY_BY_USER_CODE = "DeviceCode.queryByUserCode"; public static final String QUERY_BY_DEVICE_CODE = "DeviceCode.queryByDeviceCode"; public static final String QUERY_EXPIRED_BY_DATE = "DeviceCode.queryExpiredByDate"; - + public static final String PARAM_USER_CODE = "userCode"; public static final String PARAM_DEVICE_CODE = "deviceCode"; public static final String PARAM_DATE = "date"; - + private Long id; private String deviceCode; private String userCode; @@ -68,11 +68,11 @@ public class DeviceCode { private Map requestParameters; private boolean approved; private AuthenticationHolderEntity authenticationHolder; - + public DeviceCode() { - + } - + public DeviceCode(String deviceCode, String userCode, Set scope, String clientId, Map params) { this.deviceCode = deviceCode; this.userCode = userCode; @@ -213,7 +213,7 @@ public boolean isApproved() { public void setApproved(boolean approved) { this.approved = approved; } - + /** * The authentication in place when this token was created. * @return the authentication @@ -231,5 +231,5 @@ public void setAuthenticationHolder(AuthenticationHolderEntity authenticationHol this.authenticationHolder = authenticationHolder; } - + } diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2AccessTokenEntity.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2AccessTokenEntity.java index ac6d3743e8..2feadc10b6 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2AccessTokenEntity.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2AccessTokenEntity.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.model; @@ -41,7 +41,6 @@ import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.OneToMany; -import javax.persistence.OneToOne; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.Transient; @@ -113,9 +112,9 @@ public class OAuth2AccessTokenEntity implements OAuth2AccessToken { private Set scope; private Set permissions; - + private ApprovedSite approvedSite; - + private Map additionalInformation = new HashMap<>(); // ephemeral map of items to be added to the OAuth token response /** @@ -297,7 +296,7 @@ public int getExpiresIn() { name = "access_token_permissions", joinColumns = @JoinColumn(name = "access_token_id"), inverseJoinColumns = @JoinColumn(name = "permission_id") - ) + ) public Set getPermissions() { return permissions; } diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2RefreshTokenEntity.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2RefreshTokenEntity.java index cd5dd3c014..a197359bf2 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2RefreshTokenEntity.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2RefreshTokenEntity.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.model; @@ -78,7 +78,7 @@ public class OAuth2RefreshTokenEntity implements OAuth2RefreshToken { private Date expiration; /** - * + * */ public OAuth2RefreshTokenEntity() { @@ -104,7 +104,7 @@ public void setId(Long id) { /** * The authentication in place when the original access token was * created - * + * * @return the authentication */ @ManyToOne diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/PKCEAlgorithm.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/PKCEAlgorithm.java index e8afdc2809..ffbde8e8a7 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/PKCEAlgorithm.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/PKCEAlgorithm.java @@ -26,8 +26,13 @@ */ public final class PKCEAlgorithm extends Algorithm { + /** + * + */ + private static final long serialVersionUID = 7752852583210088925L; + public static final PKCEAlgorithm plain = new PKCEAlgorithm("plain", Requirement.REQUIRED); - + public static final PKCEAlgorithm S256 = new PKCEAlgorithm("S256", Requirement.OPTIONAL); public PKCEAlgorithm(String name, Requirement req) { @@ -37,7 +42,7 @@ public PKCEAlgorithm(String name, Requirement req) { public PKCEAlgorithm(String name) { super(name, null); } - + public static PKCEAlgorithm parse(final String s) { if (s.equals(plain.getName())) { return plain; @@ -47,7 +52,7 @@ public static PKCEAlgorithm parse(final String s) { return new PKCEAlgorithm(s); } } - - - + + + } diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClient.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClient.java index 83baeb1548..52b46f97d0 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClient.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/RegisteredClient.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.model; @@ -50,7 +50,7 @@ public class RegisteredClient { private JsonObject src; /** - * + * */ public RegisteredClient() { this.client = new ClientDetailsEntity(); @@ -815,7 +815,7 @@ public JWT getSoftwareStatement() { public void setSoftwareStatement(JWT softwareStatement) { client.setSoftwareStatement(softwareStatement); } - + /** * @return * @see org.mitre.oauth2.model.ClientDetailsEntity#getCodeChallengeMethod() diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/SavedUserAuthentication.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/SavedUserAuthentication.java index 47e531d656..77872fcab4 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/SavedUserAuthentication.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/SavedUserAuthentication.java @@ -40,7 +40,7 @@ /** * This class stands in for an original Authentication object. - * + * * @author jricher * */ diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/SystemScope.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/SystemScope.java index 8d03eef870..51539b9824 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/SystemScope.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/SystemScope.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.model; @@ -28,7 +28,6 @@ import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.Table; -import javax.persistence.Transient; /** * @author jricher diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/SerializableStringConverter.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/SerializableStringConverter.java index 7df1b5bb4b..fc11186d78 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/SerializableStringConverter.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/convert/SerializableStringConverter.java @@ -30,9 +30,9 @@ * Translates a Serializable object of certain primitive types * into a String for storage in the database, for use with the * OAuth2Request extensions map. - * + * * This class does allow some extension data to be lost. - * + * * @author jricher * */ diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthenticationHolderRepository.java b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthenticationHolderRepository.java index 8d46e23be5..fde82b1e7f 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthenticationHolderRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthenticationHolderRepository.java @@ -32,5 +32,5 @@ public interface AuthenticationHolderRepository { public List getOrphanedAuthenticationHolders(); - public List getOrphanedAuthenticationHolders(PageCriteria pageCriteria); + public List getOrphanedAuthenticationHolders(PageCriteria pageCriteria); } diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthorizationCodeRepository.java b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthorizationCodeRepository.java index f05cc7cf4a..98becf10a9 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthorizationCodeRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthorizationCodeRepository.java @@ -23,7 +23,7 @@ /** * Interface for saving and consuming OAuth2 authorization codes as AuthorizationCodeEntitys. - * + * * @author aanganes * */ @@ -31,7 +31,7 @@ public interface AuthorizationCodeRepository { /** * Save an AuthorizationCodeEntity to the repository - * + * * @param authorizationCode the AuthorizationCodeEntity to save * @return the saved AuthorizationCodeEntity */ @@ -39,7 +39,7 @@ public interface AuthorizationCodeRepository { /** * Get an authorization code from the repository by value. - * + * * @param code the authorization code value * @return the authentication associated with the code */ @@ -47,7 +47,7 @@ public interface AuthorizationCodeRepository { /** * Remove an authorization code from the repository - * + * * @param authorizationCodeEntity */ public void remove(AuthorizationCodeEntity authorizationCodeEntity); @@ -57,10 +57,10 @@ public interface AuthorizationCodeRepository { */ public Collection getExpiredCodes(); - /** - * @return A collection of all expired codes, limited by the given - * PageCriteria. - */ - public Collection getExpiredCodes(PageCriteria pageCriteria); + /** + * @return A collection of all expired codes, limited by the given + * PageCriteria. + */ + public Collection getExpiredCodes(PageCriteria pageCriteria); } diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2TokenRepository.java b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2TokenRepository.java index 6d8c2e6e42..e43670c11a 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2TokenRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2TokenRepository.java @@ -58,38 +58,38 @@ public interface OAuth2TokenRepository { public Set getAllExpiredAccessTokens(); - public Set getAllExpiredAccessTokens(PageCriteria pageCriteria); + public Set getAllExpiredAccessTokens(PageCriteria pageCriteria); public Set getAllExpiredRefreshTokens(); - public Set getAllExpiredRefreshTokens(PageCriteria pageCriteria); + public Set getAllExpiredRefreshTokens(PageCriteria pageCriteria); public Set getAccessTokensForResourceSet(ResourceSet rs); - /** - * removes duplicate access tokens. - * - * @deprecated this method was added to return the remove duplicate access tokens values - * so that {code removeAccessToken(OAuth2AccessTokenEntity o)} would not to fail. the - * removeAccessToken method has been updated so as it will not fail in the event that an - * accessToken has been duplicated, so this method is unnecessary. - * - */ - @Deprecated + /** + * removes duplicate access tokens. + * + * @deprecated this method was added to return the remove duplicate access tokens values + * so that {code removeAccessToken(OAuth2AccessTokenEntity o)} would not to fail. the + * removeAccessToken method has been updated so as it will not fail in the event that an + * accessToken has been duplicated, so this method is unnecessary. + * + */ + @Deprecated public void clearDuplicateAccessTokens(); - /** - * removes duplicate refresh tokens. - * - * @deprecated this method was added to return the remove duplicate refresh token value - * so that {code removeRefreshToken(OAuth2RefreshTokenEntity o)} would not to fail. the - * removeRefreshToken method has been updated so as it will not fail in the event that - * refreshToken has been duplicated, so this method is unnecessary. - * - */ - @Deprecated + /** + * removes duplicate refresh tokens. + * + * @deprecated this method was added to return the remove duplicate refresh token value + * so that {code removeRefreshToken(OAuth2RefreshTokenEntity o)} would not to fail. the + * removeRefreshToken method has been updated so as it will not fail in the event that + * refreshToken has been duplicated, so this method is unnecessary. + * + */ + @Deprecated public void clearDuplicateRefreshTokens(); - + public List getAccessTokensForApprovedSite(ApprovedSite approvedSite); } diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/SystemScopeRepository.java b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/SystemScopeRepository.java index 89ef891f56..b79b1d1acf 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/SystemScopeRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/SystemScopeRepository.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.repository; diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/impl/DeviceCodeRepository.java b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/impl/DeviceCodeRepository.java index 011fd24c2a..7b37706002 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/impl/DeviceCodeRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/impl/DeviceCodeRepository.java @@ -18,7 +18,6 @@ package org.mitre.oauth2.repository.impl; import java.util.Collection; -import java.util.Set; import org.mitre.oauth2.model.DeviceCode; diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java b/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java index 958dbc1d51..a0067b909a 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java @@ -24,7 +24,6 @@ import org.mitre.oauth2.model.DeviceCode; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; /** * @author jricher @@ -40,7 +39,7 @@ public interface DeviceCodeService { /** * @param dc - * @param o2Auth + * @param o2Auth */ public DeviceCode approveDeviceCode(DeviceCode dc, OAuth2Authentication o2Auth); diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/service/SystemScopeService.java b/openid-connect-common/src/main/java/org/mitre/oauth2/service/SystemScopeService.java index d7d1f800ec..b227c4a062 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/service/SystemScopeService.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/service/SystemScopeService.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.service; @@ -37,12 +37,12 @@ public interface SystemScopeService { public static final String RESOURCE_TOKEN_SCOPE = "resource-token"; // this scope manages client-style protected resources public static final String UMA_PROTECTION_SCOPE = "uma_protection"; public static final String UMA_AUTHORIZATION_SCOPE = "uma_authorization"; - - public static final Set reservedScopes = - Sets.newHashSet( - new SystemScope(REGISTRATION_TOKEN_SCOPE), - new SystemScope(RESOURCE_TOKEN_SCOPE) - ); + + public static final Set reservedScopes = + Sets.newHashSet( + new SystemScope(REGISTRATION_TOKEN_SCOPE), + new SystemScope(RESOURCE_TOKEN_SCOPE) + ); public Set getAll(); @@ -56,7 +56,7 @@ public interface SystemScopeService { * Get all the reserved system scopes. These can't be used * by clients directly, but are instead tied to special system * tokens like id tokens and registration access tokens. - * + * * @return */ public Set getReserved(); diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/service/impl/DefaultClientUserDetailsService.java b/openid-connect-common/src/main/java/org/mitre/oauth2/service/impl/DefaultClientUserDetailsService.java index f713a80be1..32a7291a32 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/service/impl/DefaultClientUserDetailsService.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/service/impl/DefaultClientUserDetailsService.java @@ -39,7 +39,7 @@ /** * Shim layer to convert a ClientDetails service into a UserDetails service - * + * * @author AANGANES * */ @@ -53,7 +53,7 @@ public class DefaultClientUserDetailsService implements UserDetailsService { @Autowired private ConfigurationPropertiesBean config; - + @Override public UserDetails loadUserByUsername(String clientId) throws UsernameNotFoundException { @@ -66,7 +66,7 @@ public UserDetails loadUserByUsername(String clientId) throws UsernameNotFoundE if (config.isHeartMode() || // if we're running HEART mode turn off all client secrets (client.getTokenEndpointAuthMethod() != null && - (client.getTokenEndpointAuthMethod().equals(AuthMethod.PRIVATE_KEY) || + (client.getTokenEndpointAuthMethod().equals(AuthMethod.PRIVATE_KEY) || client.getTokenEndpointAuthMethod().equals(AuthMethod.SECRET_JWT)))) { // Issue a random password each time to prevent password auth from being used (or skipped) diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/service/impl/UriEncodedClientUserDetailsService.java b/openid-connect-common/src/main/java/org/mitre/oauth2/service/impl/UriEncodedClientUserDetailsService.java index 774f503eb7..c85fa2da63 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/service/impl/UriEncodedClientUserDetailsService.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/service/impl/UriEncodedClientUserDetailsService.java @@ -41,9 +41,9 @@ /** * Loads client details based on URI encoding as passed in from basic auth. - * + * * Should only get called if non-encoded provider fails. - * + * * @author AANGANES * */ @@ -57,7 +57,7 @@ public class UriEncodedClientUserDetailsService implements UserDetailsService { @Autowired private ConfigurationPropertiesBean config; - + @Override public UserDetails loadUserByUsername(String clientId) throws UsernameNotFoundException { diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/ClientDetailsEntityJsonProcessor.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/ClientDetailsEntityJsonProcessor.java index 6957d685b0..f7006e1661 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/ClientDetailsEntityJsonProcessor.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/ClientDetailsEntityJsonProcessor.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect; @@ -95,7 +95,7 @@ /** * Utility class to handle the parsing and serialization of ClientDetails objects. - * + * * @author jricher * */ @@ -104,11 +104,11 @@ public class ClientDetailsEntityJsonProcessor { private static Logger logger = LoggerFactory.getLogger(ClientDetailsEntityJsonProcessor.class); private static JsonParser parser = new JsonParser(); - + /** - * + * * Create an unbound ClientDetailsEntity from the given JSON string. - * + * * @param jsonString * @return the entity if successful, null otherwise */ @@ -205,26 +205,26 @@ public static ClientDetailsEntity parse(JsonElement jsonEl) { c.setRequestUris(getAsStringSet(o, REQUEST_URIS)); c.setClaimsRedirectUris(getAsStringSet(o, CLAIMS_REDIRECT_URIS)); - + c.setCodeChallengeMethod(getAsPkceAlgorithm(o, CODE_CHALLENGE_METHOD)); - + c.setSoftwareId(getAsString(o, SOFTWARE_ID)); c.setSoftwareVersion(getAsString(o, SOFTWARE_VERSION)); - + // note that this does not process or validate the software statement, that's handled in other components String softwareStatement = getAsString(o, SOFTWARE_STATEMENT); if (!Strings.isNullOrEmpty(softwareStatement)) { try { - JWT softwareStatementJwt = JWTParser.parse(softwareStatement); - c.setSoftwareStatement(softwareStatementJwt); + JWT softwareStatementJwt = JWTParser.parse(softwareStatement); + c.setSoftwareStatement(softwareStatementJwt); } catch (ParseException e) { logger.warn("Error parsing software statement", e); return null; } } - - - + + + return c; } else { return null; @@ -345,18 +345,18 @@ public static JsonObject serialize(RegisteredClient c) { o.addProperty(INITIATE_LOGIN_URI, c.getInitiateLoginUri()); o.add(POST_LOGOUT_REDIRECT_URIS, getAsArray(c.getPostLogoutRedirectUris())); o.add(REQUEST_URIS, getAsArray(c.getRequestUris())); - + o.add(CLAIMS_REDIRECT_URIS, getAsArray(c.getClaimsRedirectUris())); - + o.addProperty(CODE_CHALLENGE_METHOD, c.getCodeChallengeMethod() != null ? c.getCodeChallengeMethod().getName() : null); - + o.addProperty(SOFTWARE_ID, c.getSoftwareId()); o.addProperty(SOFTWARE_VERSION, c.getSoftwareVersion()); - + if (c.getSoftwareStatement() != null) { o.addProperty(SOFTWARE_STATEMENT, c.getSoftwareStatement().serialize()); } - + return o; } diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationBeanLocaleResolver.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationBeanLocaleResolver.java index 2cf1b45b5c..d79c8d0f1f 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationBeanLocaleResolver.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationBeanLocaleResolver.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.config; @@ -28,13 +28,12 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.i18n.LocaleContext; import org.springframework.context.i18n.TimeZoneAwareLocaleContext; -import org.springframework.stereotype.Component; import org.springframework.web.servlet.i18n.AbstractLocaleContextResolver; /** - * + * * Resolve the server's locale from the injected ConfigurationPropertiesBean. - * + * * @author jricher * */ diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationPropertiesBean.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationPropertiesBean.java index ddae448a2a..e68938a8c1 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationPropertiesBean.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationPropertiesBean.java @@ -35,7 +35,7 @@ * Bean to hold configuration information that must be injected into various parts * of our application. Set all of the properties here, and autowire a reference * to this bean if you need access to any configuration properties. - * + * * @author AANGANES * */ @@ -49,7 +49,7 @@ public class ConfigurationPropertiesBean { private String issuer; private String topbarTitle; - + private String shortTopbarTitle; private String logoImageUrl; @@ -61,14 +61,14 @@ public class ConfigurationPropertiesBean { private boolean forceHttps = false; // by default we just log a warning for HTTPS deployment private Locale locale = Locale.ENGLISH; // we default to the english translation - + private List languageNamespaces = Lists.newArrayList("messages"); - private boolean dualClient = false; - - private boolean heartMode = false; + private boolean dualClient = false; - public ConfigurationPropertiesBean() { + private boolean heartMode = false; + + public ConfigurationPropertiesBean() { } @@ -87,7 +87,7 @@ public void checkConfigConsistency() { logger.warn("\n\n**\n** WARNING: Configured issuer url is not using https scheme.\n**\n\n"); } } - + if (languageNamespaces == null || languageNamespaces.isEmpty()) { logger.error("No configured language namespaces! Text rendering will fail!"); } @@ -120,14 +120,14 @@ public String getTopbarTitle() { public void setTopbarTitle(String topbarTitle) { this.topbarTitle = topbarTitle; } - + /** - * @return If shortTopbarTitle is undefined, returns topbarTitle. + * @return If shortTopbarTitle is undefined, returns topbarTitle. */ public String getShortTopbarTitle() { return shortTopbarTitle == null ? topbarTitle : shortTopbarTitle; } - + public void setShortTopbarTitle(String shortTopbarTitle) { this.shortTopbarTitle = shortTopbarTitle; } @@ -211,37 +211,37 @@ public void setLanguageNamespaces(List languageNamespaces) { } /** - * @return true if dual client is configured, otherwise false - */ - public boolean isDualClient() { - if (isHeartMode()) { - return false; // HEART mode is incompatible with dual client mode - } else { - return dualClient; - } - } - - /** - * @param dualClient the dual client configuration - */ - public void setDualClient(boolean dualClient) { - this.dualClient = dualClient; - } - - /** - * Get the list of namespaces as a JSON string, for injection into the JavaScript UI - * @return - */ - public String getLanguageNamespacesString() { - return new Gson().toJson(getLanguageNamespaces()); - } - - /** - * Get the default namespace (first in the nonempty list) - */ - public String getDefaultLanguageNamespace() { - return getLanguageNamespaces().get(0); - } + * @return true if dual client is configured, otherwise false + */ + public boolean isDualClient() { + if (isHeartMode()) { + return false; // HEART mode is incompatible with dual client mode + } else { + return dualClient; + } + } + + /** + * @param dualClient the dual client configuration + */ + public void setDualClient(boolean dualClient) { + this.dualClient = dualClient; + } + + /** + * Get the list of namespaces as a JSON string, for injection into the JavaScript UI + * @return + */ + public String getLanguageNamespacesString() { + return new Gson().toJson(getLanguageNamespaces()); + } + + /** + * Get the default namespace (first in the nonempty list) + */ + public String getDefaultLanguageNamespace() { + return getLanguageNamespaces().get(0); + } /** * @return the heartMode diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/config/JWKSetEditor.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/config/JWKSetEditor.java index c9fb8988c0..e02ea4fa74 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/config/JWKSetEditor.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/config/JWKSetEditor.java @@ -25,7 +25,7 @@ /** * Allows JWK Set strings to be used in XML configurations. - * + * * @author jricher * */ diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ServerConfiguration.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ServerConfiguration.java index b80f1633b8..39d53f0bea 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ServerConfiguration.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/config/ServerConfiguration.java @@ -25,16 +25,16 @@ /** - * + * * Container class for a client's view of a server's configuration - * + * * @author nemonik, jricher - * + * */ public class ServerConfiguration { /* - * + * issuer REQUIRED. URL using the https scheme with no query or fragment component that the OP asserts as its Issuer Identifier. authorization_endpoint diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/config/UIConfiguration.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/config/UIConfiguration.java index 7bc689d847..7890b6964e 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/config/UIConfiguration.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/config/UIConfiguration.java @@ -20,9 +20,9 @@ import java.util.Set; /** - * + * * Bean for UI (front-end) configuration to be read at start-up. - * + * * @author jricher * */ @@ -30,7 +30,7 @@ public class UIConfiguration { private Set jsFiles; private Set templateFiles; - + /** * @return the jsFiles */ @@ -55,5 +55,5 @@ public Set getTemplateFiles() { public void setTemplateFiles(Set templateFiles) { this.templateFiles = templateFiles; } - + } diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/Address.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/Address.java index 59e6866715..be0ea60798 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/Address.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/Address.java @@ -25,62 +25,62 @@ public interface Address extends Serializable { * @return */ public Long getId(); - + /** * @return the formatted address */ public String getFormatted(); - + /** * @param formatted the formatted address to set */ public void setFormatted(String formatted); - + /** * @return the streetAddress */ public String getStreetAddress(); - + /** * @param streetAddress the streetAddress to set */ public void setStreetAddress(String streetAddress); - + /** * @return the locality */ public String getLocality(); - + /** * @param locality the locality to set */ public void setLocality(String locality); - + /** * @return the region */ public String getRegion(); - + /** * @param region the region to set */ public void setRegion(String region); - + /** * @return the postalCode */ public String getPostalCode(); - + /** * @param postalCode the postalCode to set */ public void setPostalCode(String postalCode); - + /** * @return the country */ public String getCountry(); - + /** * @param country the country to set */ diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ApprovedSite.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ApprovedSite.java index 6be0bb8f41..e4f8e5c8d8 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ApprovedSite.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ApprovedSite.java @@ -20,7 +20,6 @@ import java.util.Set; import javax.persistence.Basic; -import javax.persistence.CascadeType; import javax.persistence.CollectionTable; import javax.persistence.Column; import javax.persistence.ElementCollection; @@ -32,15 +31,10 @@ import javax.persistence.JoinColumn; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; -import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.Transient; -import org.mitre.oauth2.model.OAuth2AccessTokenEntity; - -import com.google.common.collect.Sets; - @Entity @Table(name="approved_site") @NamedQueries({ diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/BlacklistedSite.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/BlacklistedSite.java index 0447151ec6..f6c1a2891f 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/BlacklistedSite.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/BlacklistedSite.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.model; diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/CachedImage.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/CachedImage.java index 7aa18d3ca4..a29732221f 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/CachedImage.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/CachedImage.java @@ -22,11 +22,11 @@ * */ public class CachedImage { - + private byte[] data; private String contentType; private long length; - + /** * @return the data */ diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ClientStat.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ClientStat.java index 585df3b2b5..b0289c98d6 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ClientStat.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ClientStat.java @@ -38,5 +38,5 @@ public Integer getApprovedSiteCount() { public void setApprovedSiteCount(Integer count) { this.approvedSiteCount = count; } - + } diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultAddress.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultAddress.java index 237d1e68ab..3093e1f6e7 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultAddress.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultAddress.java @@ -16,8 +16,6 @@ *******************************************************************************/ package org.mitre.openid.connect.model; -import java.io.Serializable; - import javax.persistence.Basic; import javax.persistence.Column; import javax.persistence.Entity; @@ -63,6 +61,7 @@ public DefaultAddress(Address address) { /** * @return the formatted address string */ + @Override @Basic @Column(name = "formatted") public String getFormatted() { @@ -71,12 +70,14 @@ public String getFormatted() { /** * @param formatted the formatted address to set */ + @Override public void setFormatted(String formatted) { this.formatted = formatted; } /** * @return the streetAddress */ + @Override @Basic @Column(name="street_address") public String getStreetAddress() { @@ -85,12 +86,14 @@ public String getStreetAddress() { /** * @param streetAddress the streetAddress to set */ + @Override public void setStreetAddress(String streetAddress) { this.streetAddress = streetAddress; } /** * @return the locality */ + @Override @Basic @Column(name = "locality") public String getLocality() { @@ -99,12 +102,14 @@ public String getLocality() { /** * @param locality the locality to set */ + @Override public void setLocality(String locality) { this.locality = locality; } /** * @return the region */ + @Override @Basic @Column(name = "region") public String getRegion() { @@ -113,12 +118,14 @@ public String getRegion() { /** * @param region the region to set */ + @Override public void setRegion(String region) { this.region = region; } /** * @return the postalCode */ + @Override @Basic @Column(name="postal_code") public String getPostalCode() { @@ -127,12 +134,14 @@ public String getPostalCode() { /** * @param postalCode the postalCode to set */ + @Override public void setPostalCode(String postalCode) { this.postalCode = postalCode; } /** * @return the country */ + @Override @Basic @Column(name = "country") public String getCountry() { @@ -141,6 +150,7 @@ public String getCountry() { /** * @param country the country to set */ + @Override public void setCountry(String country) { this.country = country; } @@ -148,6 +158,7 @@ public void setCountry(String country) { /** * @return the id */ + @Override @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name = "id") diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultUserInfo.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultUserInfo.java index 97c9d57ddd..5fe70b5c07 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultUserInfo.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultUserInfo.java @@ -379,7 +379,7 @@ public Address getAddress() { */ @Override public void setAddress(Address address) { - if (address != null) { + if (address != null) { this.address = new DefaultAddress(address); } else { this.address = null; @@ -499,7 +499,7 @@ public static UserInfo fromJson(JsonObject obj) { ui.setPhoneNumber(nullSafeGetString(obj, "phone_number")); ui.setPhoneNumberVerified(obj.has("phone_number_verified") && obj.get("phone_number_verified").isJsonPrimitive() ? obj.get("phone_number_verified").getAsBoolean() : null); - + if (obj.has("address") && obj.get("address").isJsonObject()) { JsonObject addr = obj.get("address").getAsJsonObject(); ui.setAddress(new DefaultAddress()); diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/OIDCAuthenticationToken.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/OIDCAuthenticationToken.java index 85be3aad6b..ca4e996b04 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/OIDCAuthenticationToken.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/OIDCAuthenticationToken.java @@ -30,9 +30,9 @@ import com.nimbusds.jwt.JWTParser; /** - * + * * @author Michael Walsh, Justin Richer - * + * */ public class OIDCAuthenticationToken extends AbstractAuthenticationToken { @@ -49,9 +49,9 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken { /** * Constructs OIDCAuthenticationToken with a full set of authorities, marking this as authenticated. - * + * * Set to authenticated. - * + * * Constructs a Principal out of the subject and issuer. * @param subject * @param authorities @@ -78,7 +78,7 @@ public OIDCAuthenticationToken(String subject, String issuer, /* * (non-Javadoc) - * + * * @see org.springframework.security.core.Authentication#getCredentials() */ @Override diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/PairwiseIdentifier.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/PairwiseIdentifier.java index c46f1b1e10..e651d8b138 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/PairwiseIdentifier.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/PairwiseIdentifier.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.model; @@ -30,9 +30,9 @@ import javax.persistence.Table; /** - * + * * Holds the generated pairwise identifiers for a user. Can be tied to either a client ID or a sector identifier URL. - * + * * @author jricher * */ diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/PendingOIDCAuthenticationToken.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/PendingOIDCAuthenticationToken.java index 70aed558c5..fbcd9d52e1 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/PendingOIDCAuthenticationToken.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/PendingOIDCAuthenticationToken.java @@ -33,7 +33,7 @@ /** * AuthenticationToken for use as a data shuttle from the filter to the auth provider. - * + * * @author jricher * */ @@ -52,9 +52,9 @@ public class PendingOIDCAuthenticationToken extends AbstractAuthenticationToken /** * Constructs OIDCAuthenticationToken for use as a data shuttle from the filter to the auth provider. - * + * * Set to not-authenticated. - * + * * Constructs a Principal out of the subject and issuer. * @param sub * @param idToken @@ -80,7 +80,7 @@ public PendingOIDCAuthenticationToken (String subject, String issuer, /* * (non-Javadoc) - * + * * @see org.springframework.security.core.Authentication#getCredentials() */ @Override diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/UserInfo.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/UserInfo.java index 543486a2ce..5029290440 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/UserInfo.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/UserInfo.java @@ -184,12 +184,12 @@ public interface UserInfo extends Serializable { public void setPhoneNumber(String phoneNumber); /** - * + * */ public Boolean getPhoneNumberVerified(); /** - * + * * @param phoneNumberVerified */ public void setPhoneNumberVerified(Boolean phoneNumberVerified); @@ -216,20 +216,20 @@ public interface UserInfo extends Serializable { /** - * + * * @return */ public String getBirthdate(); /** - * + * * @param birthdate */ public void setBirthdate(String birthdate); /** * Serialize this UserInfo object to JSON. - * + * * @return */ public JsonObject toJson(); diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/AddressRepository.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/AddressRepository.java index 1730093133..84352e4d88 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/AddressRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/AddressRepository.java @@ -28,7 +28,7 @@ public interface AddressRepository { /** * Returns the Address for the given id - * + * * @param id * id the id of the Address * @return a valid Address if it exists, null otherwise diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/ApprovedSiteRepository.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/ApprovedSiteRepository.java index 1919254b14..502fd1b22a 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/ApprovedSiteRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/ApprovedSiteRepository.java @@ -30,7 +30,7 @@ public interface ApprovedSiteRepository { /** * Returns the ApprovedSite for the given id - * + * * @param id * id the id of the ApprovedSite * @return a valid ApprovedSite if it exists, null otherwise @@ -39,7 +39,7 @@ public interface ApprovedSiteRepository { /** * Return a collection of all ApprovedSites managed by this repository - * + * * @return the ApprovedSite collection, or null */ public Collection getAll(); @@ -47,7 +47,7 @@ public interface ApprovedSiteRepository { /** * Return a collection of ApprovedSite managed by this repository matching the * provided client ID and user ID - * + * * @param clientId * @param userId * @return @@ -56,7 +56,7 @@ public interface ApprovedSiteRepository { /** * Removes the given ApprovedSite from the repository - * + * * @param aggregator * the ApprovedSite object to remove */ @@ -64,7 +64,7 @@ public interface ApprovedSiteRepository { /** * Persists an ApprovedSite - * + * * @param aggregator * valid ApprovedSite instance * @return the persisted entity diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/BlacklistedSiteRepository.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/BlacklistedSiteRepository.java index cab432ac68..2e98faf982 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/BlacklistedSiteRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/BlacklistedSiteRepository.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.repository; diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/PairwiseIdentifierRepository.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/PairwiseIdentifierRepository.java index 1a168d7a1d..4bf1ea3130 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/PairwiseIdentifierRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/PairwiseIdentifierRepository.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.repository; @@ -29,7 +29,7 @@ public interface PairwiseIdentifierRepository { /** * Get a pairwise identifier by its associated user subject and sector identifier. - * + * * @param sub * @param sectorIdentifierUri * @return @@ -38,7 +38,7 @@ public interface PairwiseIdentifierRepository { /** * Save a pairwise identifier to the database. - * + * * @param pairwise */ public void save(PairwiseIdentifier pairwise); diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/UserInfoRepository.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/UserInfoRepository.java index 9ea3011d53..99dcb5570b 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/UserInfoRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/UserInfoRepository.java @@ -20,7 +20,7 @@ /** * UserInfo repository interface - * + * * @author Michael Joseph Walsh * */ @@ -34,9 +34,9 @@ public interface UserInfoRepository { public UserInfo getByUsername(String username); /** - * + * * Get the UserInfo object by its email field - * + * * @param email * @return */ diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/WhitelistedSiteRepository.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/WhitelistedSiteRepository.java index 1e6f91028d..3452078563 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/WhitelistedSiteRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/WhitelistedSiteRepository.java @@ -22,22 +22,22 @@ /** * WhitelistedSite repository interface - * + * * @author Michael Joseph Walsh, aanganes - * + * */ public interface WhitelistedSiteRepository { /** * Return a collection of all WhitelistedSite managed by this repository - * + * * @return the WhitelistedSite collection, or null */ public Collection getAll(); /** * Returns the WhitelistedSite for the given id - * + * * @param id * id the id of the WhitelistedSite * @return a valid WhitelistedSite if it exists, null otherwise @@ -46,7 +46,7 @@ public interface WhitelistedSiteRepository { /** * Find a WhitelistedSite by its associated ClientDetails reference - * + * * @param client the Relying Party * @return the corresponding WhitelistedSite if one exists for the RP, or null */ @@ -54,7 +54,7 @@ public interface WhitelistedSiteRepository { /** * Return a collection of the WhitelistedSites created by a given user - * + * * @param creator the id of the admin who may have created some WhitelistedSites * @return the collection of corresponding WhitelistedSites, if any, or null */ @@ -62,7 +62,7 @@ public interface WhitelistedSiteRepository { /** * Removes the given IdToken from the repository - * + * * @param whitelistedSite * the WhitelistedSite object to remove */ @@ -70,7 +70,7 @@ public interface WhitelistedSiteRepository { /** * Persists a WhitelistedSite - * + * * @param whitelistedSite * @return */ diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/ApprovedSiteService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/ApprovedSiteService.java index 23b5519b92..bfc1f71224 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/ApprovedSiteService.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/ApprovedSiteService.java @@ -27,9 +27,9 @@ /** * Interface for ApprovedSite service - * + * * @author Michael Joseph Walsh, aanganes - * + * */ public interface ApprovedSiteService { @@ -38,7 +38,7 @@ public interface ApprovedSiteService { /** * Return a collection of all ApprovedSites - * + * * @return the ApprovedSite collection, or null */ public Collection getAll(); @@ -46,7 +46,7 @@ public interface ApprovedSiteService { /** * Return a collection of ApprovedSite managed by this repository matching the * provided client ID and user ID - * + * * @param clientId * @param userId * @return @@ -55,7 +55,7 @@ public interface ApprovedSiteService { /** * Save an ApprovedSite - * + * * @param approvedSite * the ApprovedSite to be saved */ @@ -63,7 +63,7 @@ public interface ApprovedSiteService { /** * Get ApprovedSite for id - * + * * @param id * id for ApprovedSite * @return ApprovedSite for id, or null @@ -72,7 +72,7 @@ public interface ApprovedSiteService { /** * Remove the ApprovedSite - * + * * @param approvedSite * the ApprovedSite to remove */ @@ -109,5 +109,5 @@ public interface ApprovedSiteService { * @return */ public List getApprovedAccessTokens(ApprovedSite approvedSite); - + } diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/BlacklistedSiteService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/BlacklistedSiteService.java index 8bb09fc175..0b2724d701 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/BlacklistedSiteService.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/BlacklistedSiteService.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.service; diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/MITREidDataService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/MITREidDataService.java index ec07f00359..c5f56b0589 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/MITREidDataService.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/MITREidDataService.java @@ -47,7 +47,7 @@ public interface MITREidDataService { /** * Write out the current server state to the given JSON writer as a JSON object - * + * * @param writer * @throws IOException */ @@ -55,15 +55,15 @@ public interface MITREidDataService { /** * Read in the current server state from the given JSON reader as a JSON object - * + * * @param reader */ void importData(JsonReader reader) throws IOException; /** - * Return true if the this data service supports the given version. This is called before + * Return true if the this data service supports the given version. This is called before * handing the service the reader through its importData function. - * + * * @param version * @return */ diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/MITREidDataServiceExtension.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/MITREidDataServiceExtension.java index 98ddd027f4..cdd9e1d6e2 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/MITREidDataServiceExtension.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/MITREidDataServiceExtension.java @@ -23,19 +23,19 @@ import com.google.gson.stream.JsonWriter; /** - * A modular extension to the data import/export layer. Any instances of this need to be + * A modular extension to the data import/export layer. Any instances of this need to be * declared as beans to be picked up by the data services. - * + * * @author jricher * */ public interface MITREidDataServiceExtension { /** - * Export any data for this extension. This is called from the top level object. + * Export any data for this extension. This is called from the top level object. * All extensions MUST return the writer to a state such that another member of * the top level object can be written next. - * + * * @param writer */ void exportExtensionData(JsonWriter writer) throws IOException; @@ -46,20 +46,20 @@ public interface MITREidDataServiceExtension { * such that another member of the top level object can be read next. The name of * the data element being imported is passed in as name. If the extension does not * support this data element, it must return without advancing the reader. - * + * * Returns "true" if the item was processed, "false" otherwise. - * + * * @param reader */ boolean importExtensionData(String name, JsonReader reader) throws IOException; /** - * Signal the extension to wrap up all object processing and finalize its + * Signal the extension to wrap up all object processing and finalize its */ void fixExtensionObjectReferences(MITREidDataServiceMaps maps); /** - * Return + * Return * @param mitreidConnect13 * @return */ diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/MITREidDataServiceMaps.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/MITREidDataServiceMaps.java index 27430c3b24..5ea918f169 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/MITREidDataServiceMaps.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/MITREidDataServiceMaps.java @@ -115,5 +115,5 @@ public void clearAll() { accessTokenOldToNewIdMap.clear(); grantOldToNewIdMap.clear(); } - + } diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/OIDCTokenService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/OIDCTokenService.java index 1b79805a2f..4c3ac5a36b 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/OIDCTokenService.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/OIDCTokenService.java @@ -26,7 +26,7 @@ /** * Service to create specialty OpenID Connect tokens. - * + * * @author Amanda Anganes * */ @@ -34,7 +34,7 @@ public interface OIDCTokenService { /** * Create an id token with the information provided. - * + * * @param client * @param request * @param issueTime @@ -49,7 +49,7 @@ public JWT createIdToken( /** * Create a registration access token for the given client. - * + * * @param client * @return */ @@ -57,7 +57,7 @@ public JWT createIdToken( /** * Create a resource access token for the given client (protected resource). - * + * * @param client * @return */ diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/PairwiseIdentiferService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/PairwiseIdentiferService.java index 41446759a9..7b524ad7b9 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/PairwiseIdentiferService.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/PairwiseIdentiferService.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.service; @@ -30,9 +30,9 @@ public interface PairwiseIdentiferService { /** * Calcualtes the pairwise identifier for the given userinfo object and client. - * + * * Returns 'null' if no identifer could be calculated. - * + * * @param userInfo * @param client * @return diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/ScopeClaimTranslationService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/ScopeClaimTranslationService.java index d5bb4ec44c..de4886203e 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/ScopeClaimTranslationService.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/ScopeClaimTranslationService.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.service; diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/StatsService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/StatsService.java index 502094b603..b129927529 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/StatsService.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/StatsService.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.service; @@ -34,14 +34,14 @@ public interface StatsService { * approvalCount: total approved sites * userCount: unique users * clientCount: unique clients - * + * * @return */ public Map getSummaryStats(); /** * Calculate the usage count for a single client - * + * * @param clientId the id of the client to search on * @return */ diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/UserInfoService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/UserInfoService.java index 5b3161b1a2..e042084027 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/UserInfoService.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/UserInfoService.java @@ -20,9 +20,9 @@ /** * Interface for UserInfo service - * + * * @author Michael Joseph Walsh - * + * */ public interface UserInfoService { @@ -46,7 +46,7 @@ public interface UserInfoService { /** * Get the user registered at this server with the given email address. - * + * * @param email * @return */ diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/WhitelistedSiteService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/WhitelistedSiteService.java index 4d805b7ac9..570f899225 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/WhitelistedSiteService.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/WhitelistedSiteService.java @@ -22,22 +22,22 @@ /** * Interface for WhitelistedSite service - * + * * @author Michael Joseph Walsh, aanganes - * + * */ public interface WhitelistedSiteService { /** * Return a collection of all WhitelistedSite managed by this service - * + * * @return the WhitelistedSite collection, or null */ public Collection getAll(); /** * Returns the WhitelistedSite for the given id - * + * * @param id * id the id of the WhitelistedSite * @return a valid WhitelistedSite if it exists, null otherwise @@ -46,7 +46,7 @@ public interface WhitelistedSiteService { /** * Find a WhitelistedSite by its associated ClientDetails reference - * + * * @param client the Relying Party * @return the corresponding WhitelistedSite if one exists for the RP, or null */ @@ -56,7 +56,7 @@ public interface WhitelistedSiteService { /** * Removes the given WhitelistedSite from the repository - * + * * @param address * the WhitelistedSite object to remove */ @@ -64,7 +64,7 @@ public interface WhitelistedSiteService { /** * Persists a new WhitelistedSite - * + * * @param whitelistedSite * the WhitelistedSite to be saved * @return diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/view/JWKSetView.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/view/JWKSetView.java index 4398a07f02..801802d5dd 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/view/JWKSetView.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/view/JWKSetView.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.view; diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/web/UserInfoInterceptor.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/web/UserInfoInterceptor.java index b9f88f5066..71fcacd284 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/web/UserInfoInterceptor.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/web/UserInfoInterceptor.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.web; @@ -44,24 +44,24 @@ /** * Injects the UserInfo object for the current user into the current model's context, if both exist. Allows JSPs and the like to call "userInfo.name" and other fields. - * + * * @author jricher * */ public class UserInfoInterceptor extends HandlerInterceptorAdapter { private Gson gson = new GsonBuilder() - .registerTypeHierarchyAdapter(GrantedAuthority.class, new JsonSerializer() { - @Override - public JsonElement serialize(GrantedAuthority src, Type typeOfSrc, JsonSerializationContext context) { - return new JsonPrimitive(src.getAuthority()); - } - }) - .create(); + .registerTypeHierarchyAdapter(GrantedAuthority.class, new JsonSerializer() { + @Override + public JsonElement serialize(GrantedAuthority src, Type typeOfSrc, JsonSerializationContext context) { + return new JsonPrimitive(src.getAuthority()); + } + }) + .create(); @Autowired (required = false) private UserInfoService userInfoService; - + private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl(); @Override @@ -72,7 +72,7 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons if (auth instanceof Authentication){ request.setAttribute("userAuthorities", gson.toJson(auth.getAuthorities())); } - + if (!trustResolver.isAnonymous(auth)) { // skip lookup on anonymous logins if (auth instanceof OIDCAuthenticationToken) { // if they're logging into this server from a remote OIDC server, pass through their user info @@ -87,10 +87,10 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons } else { // don't bother checking if we don't have a principal or a userInfoService to work with if (auth != null && auth.getName() != null && userInfoService != null) { - + // try to look up a user based on the principal's name UserInfo user = userInfoService.getByUsername(auth.getName()); - + // if we have one, inject it so views can use it if (user != null) { request.setAttribute("userInfo", user); diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/Claim.java b/openid-connect-common/src/main/java/org/mitre/uma/model/Claim.java index 4b735e866e..d8f9bde9cb 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/Claim.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/Claim.java @@ -118,9 +118,9 @@ public void setClaimType(String claimType) { @ElementCollection(fetch = FetchType.EAGER) @Column(name = "claim_token_format") @CollectionTable( - name = "claim_token_format", - joinColumns = @JoinColumn(name = "owner_id") - ) + name = "claim_token_format", + joinColumns = @JoinColumn(name = "owner_id") + ) public Set getClaimTokenFormat() { return claimTokenFormat; } @@ -137,9 +137,9 @@ public void setClaimTokenFormat(Set claimTokenFormat) { @ElementCollection(fetch = FetchType.EAGER) @Column(name = "issuer") @CollectionTable( - name = "claim_issuer", - joinColumns = @JoinColumn(name = "owner_id") - ) + name = "claim_issuer", + joinColumns = @JoinColumn(name = "owner_id") + ) public Set getIssuer() { return issuer; } diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/ClaimProcessingResult.java b/openid-connect-common/src/main/java/org/mitre/uma/model/ClaimProcessingResult.java index f6b00cf228..962918eeb4 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/ClaimProcessingResult.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/ClaimProcessingResult.java @@ -21,7 +21,7 @@ /** * Data shuttle to return results of the claims processing service. - * + * * @author jricher * */ diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/Permission.java b/openid-connect-common/src/main/java/org/mitre/uma/model/Permission.java index d856ef8477..5a8ff06e21 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/Permission.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/Permission.java @@ -81,9 +81,9 @@ public void setResourceSet(ResourceSet resourceSet) { @ElementCollection(fetch = FetchType.EAGER) @Column(name = "scope") @CollectionTable( - name = "permission_scope", - joinColumns = @JoinColumn(name = "owner_id") - ) + name = "permission_scope", + joinColumns = @JoinColumn(name = "owner_id") + ) public Set getScopes() { return scopes; } diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/PermissionTicket.java b/openid-connect-common/src/main/java/org/mitre/uma/model/PermissionTicket.java index ce02deecd4..70097572ca 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/PermissionTicket.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/PermissionTicket.java @@ -39,9 +39,9 @@ import javax.persistence.TemporalType; /** - * + * * An UMA permission, used in the protection API. - * + * * @author jricher * */ @@ -141,7 +141,7 @@ public void setExpiration(Date expiration) { name = "claim_to_permission_ticket", joinColumns = @JoinColumn(name = "permission_ticket_id"), inverseJoinColumns = @JoinColumn(name = "claim_id") - ) + ) public Collection getClaimsSupplied() { return claimsSupplied; } diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/Policy.java b/openid-connect-common/src/main/java/org/mitre/uma/model/Policy.java index c29a05208c..14714a4ed7 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/Policy.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/Policy.java @@ -37,7 +37,7 @@ /** * A set of claims required to fulfill a given permission. - * + * * @author jricher * */ @@ -109,9 +109,9 @@ public void setClaimsRequired(Collection claimsRequired) { @ElementCollection(fetch = FetchType.EAGER) @Column(name = "scope") @CollectionTable( - name = "policy_scope", - joinColumns = @JoinColumn(name = "owner_id") - ) + name = "policy_scope", + joinColumns = @JoinColumn(name = "owner_id") + ) public Set getScopes() { return scopes; } diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/ResourceSet.java b/openid-connect-common/src/main/java/org/mitre/uma/model/ResourceSet.java index 8922ad91f6..6ea39176f6 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/ResourceSet.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/ResourceSet.java @@ -137,9 +137,9 @@ public void setType(String type) { @ElementCollection(fetch = FetchType.EAGER) @Column(name = "scope") @CollectionTable( - name = "resource_set_scope", - joinColumns = @JoinColumn(name = "owner_id") - ) + name = "resource_set_scope", + joinColumns = @JoinColumn(name = "owner_id") + ) public Set getScopes() { return scopes; } diff --git a/openid-connect-common/src/main/java/org/mitre/uma/model/SavedRegisteredClient.java b/openid-connect-common/src/main/java/org/mitre/uma/model/SavedRegisteredClient.java index c65aa8d851..03ae277e4a 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/model/SavedRegisteredClient.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/model/SavedRegisteredClient.java @@ -52,7 +52,7 @@ public Long getId() { } /** - * + * * @param id the id to set */ public void setId(Long id) { diff --git a/openid-connect-common/src/main/java/org/mitre/uma/repository/PermissionRepository.java b/openid-connect-common/src/main/java/org/mitre/uma/repository/PermissionRepository.java index 816e70866f..fc46086134 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/repository/PermissionRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/repository/PermissionRepository.java @@ -30,9 +30,9 @@ public interface PermissionRepository { /** - * + * * Save a permission ticket. - * + * * @param p * @return */ @@ -40,7 +40,7 @@ public interface PermissionRepository { /** * Get the permission indicated by its ticket value. - * + * * @param ticket * @return */ @@ -48,14 +48,14 @@ public interface PermissionRepository { /** * Get all the tickets in the system (used by the import/export API) - * + * * @return */ public Collection getAll(); /** * Save a permission object with no associated ticket (used by the import/export API) - * + * * @param p * @return */ @@ -63,7 +63,7 @@ public interface PermissionRepository { /** * Get a permission object by its ID (used by the import/export API) - * + * * @param permissionId * @return */ @@ -71,7 +71,7 @@ public interface PermissionRepository { /** * Get all permission tickets issued against a resource set (called when RS is deleted) - * + * * @param rs * @return */ @@ -79,7 +79,7 @@ public interface PermissionRepository { /** * Remove the specified ticket. - * + * * @param ticket */ public void remove(PermissionTicket ticket); diff --git a/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java b/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java index 202a3f8805..f863a577ff 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/service/ClaimsProcessingService.java @@ -22,20 +22,20 @@ import org.mitre.uma.model.ResourceSet; /** - * + * * Processes claims presented during an UMA transaction. - * + * * @author jricher * */ public interface ClaimsProcessingService { /** - * + * * Determine whether or not the claims that have been supplied are * sufficient to fulfill the requirements given by the claims that * are required. - * + * * @param rs the required claims to check against * @param ticket the supplied claims to test * @return the result of the claims processing action diff --git a/openid-connect-common/src/main/java/org/mitre/uma/service/PermissionService.java b/openid-connect-common/src/main/java/org/mitre/uma/service/PermissionService.java index 1f6e547d6b..1c76fc99c2 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/service/PermissionService.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/service/PermissionService.java @@ -39,9 +39,9 @@ public interface PermissionService { public PermissionTicket createTicket(ResourceSet resourceSet, Set scopes); /** - * + * * Read the permission associated with the given ticket. - * + * * @param the ticket value to search on * @return the permission object, or null if none is found */ @@ -49,7 +49,7 @@ public interface PermissionService { /** * Save the updated permission ticket to the database. Does not create a new ticket. - * + * * @param ticket * @return */ diff --git a/openid-connect-common/src/main/java/org/mitre/uma/service/ResourceSetService.java b/openid-connect-common/src/main/java/org/mitre/uma/service/ResourceSetService.java index 5d990faac5..22b2f0f8a3 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/service/ResourceSetService.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/service/ResourceSetService.java @@ -22,9 +22,9 @@ import org.mitre.uma.model.ResourceSet; /** - * + * * Manage registered resource sets at this authorization server. - * + * * @author jricher * */ diff --git a/openid-connect-common/src/main/java/org/mitre/uma/service/SavedRegisteredClientService.java b/openid-connect-common/src/main/java/org/mitre/uma/service/SavedRegisteredClientService.java index ee3e5329a7..eab15c01fa 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/service/SavedRegisteredClientService.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/service/SavedRegisteredClientService.java @@ -27,10 +27,10 @@ * */ public interface SavedRegisteredClientService { - + /** * Get a list of all the registered clients that we know about. - * + * * @return */ Collection getAll(); diff --git a/openid-connect-common/src/main/java/org/mitre/uma/service/UmaTokenService.java b/openid-connect-common/src/main/java/org/mitre/uma/service/UmaTokenService.java index 96b1277b5e..ccea01368f 100644 --- a/openid-connect-common/src/main/java/org/mitre/uma/service/UmaTokenService.java +++ b/openid-connect-common/src/main/java/org/mitre/uma/service/UmaTokenService.java @@ -24,7 +24,7 @@ /** * Service to create special tokens for UMA. - * + * * @author jricher * */ @@ -32,7 +32,7 @@ public interface UmaTokenService { /** * Create the RPT from the given authentication and ticket. - * + * */ public OAuth2AccessTokenEntity createRequestingPartyToken(OAuth2Authentication o2auth, PermissionTicket ticket, Policy policy); diff --git a/openid-connect-common/src/main/java/org/mitre/util/JsonUtils.java b/openid-connect-common/src/main/java/org/mitre/util/JsonUtils.java index dc2c53f951..50cae7060f 100644 --- a/openid-connect-common/src/main/java/org/mitre/util/JsonUtils.java +++ b/openid-connect-common/src/main/java/org/mitre/util/JsonUtils.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.util; @@ -48,7 +48,7 @@ /** * A collection of null-safe converters from common classes and JSON elements, using GSON. - * + * * @author jricher * */ @@ -86,7 +86,7 @@ public static JsonElement getAsArray(Set value, boolean preserveEmpty) { return gson.toJsonTree(value, new TypeToken>(){}.getType()); } } - + /** * Gets the value of the given member (expressed as integer seconds since epoch) as a Date */ @@ -287,19 +287,19 @@ public static Map readMap(JsonReader reader) throws IOException { String name = reader.nextName(); Object value = null; switch(reader.peek()) { - case STRING: - value = reader.nextString(); - break; - case BOOLEAN: - value = reader.nextBoolean(); - break; - case NUMBER: - value = reader.nextLong(); - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + case STRING: + value = reader.nextString(); + break; + case BOOLEAN: + value = reader.nextBoolean(); + break; + case NUMBER: + value = reader.nextLong(); + break; + default: + logger.debug("Found unexpected entry"); + reader.skipValue(); + continue; } map.put(name, value); } @@ -311,21 +311,21 @@ public static Set readSet(JsonReader reader) throws IOException { Set arraySet = null; reader.beginArray(); switch (reader.peek()) { - case STRING: - arraySet = new HashSet<>(); - while (reader.hasNext()) { - arraySet.add(reader.nextString()); - } - break; - case NUMBER: - arraySet = new HashSet<>(); - while (reader.hasNext()) { - arraySet.add(reader.nextLong()); - } - break; - default: - arraySet = new HashSet(); - break; + case STRING: + arraySet = new HashSet<>(); + while (reader.hasNext()) { + arraySet.add(reader.nextString()); + } + break; + case NUMBER: + arraySet = new HashSet<>(); + while (reader.hasNext()) { + arraySet.add(reader.nextLong()); + } + break; + default: + arraySet = new HashSet(); + break; } reader.endArray(); return arraySet; diff --git a/openid-connect-common/src/main/java/org/mitre/util/jpa/JpaUtil.java b/openid-connect-common/src/main/java/org/mitre/util/jpa/JpaUtil.java index c6fa2c6df4..15d3ea0e2d 100644 --- a/openid-connect-common/src/main/java/org/mitre/util/jpa/JpaUtil.java +++ b/openid-connect-common/src/main/java/org/mitre/util/jpa/JpaUtil.java @@ -16,48 +16,48 @@ *******************************************************************************/ package org.mitre.util.jpa; -import org.mitre.data.PageCriteria; - import java.util.List; import javax.persistence.EntityManager; import javax.persistence.TypedQuery; +import org.mitre.data.PageCriteria; + /** * @author mfranklin * Date: 4/28/11 * Time: 2:13 PM */ public class JpaUtil { - public static T getSingleResult(List list) { + public static T getSingleResult(List list) { switch(list.size()) { - case 0: - return null; - case 1: - return list.get(0); - default: - throw new IllegalStateException("Expected single result, got " + list.size()); + case 0: + return null; + case 1: + return list.get(0); + default: + throw new IllegalStateException("Expected single result, got " + list.size()); } } - /** - * Get a page of results from the specified TypedQuery - * by using the given PageCriteria to limit the query - * results. The PageCriteria will override any size or - * offset already specified on the query. - * - * @param the type parameter - * @param query the query - * @param pageCriteria the page criteria - * @return the list - */ - public static List getResultPage(TypedQuery query, PageCriteria pageCriteria){ - query.setMaxResults(pageCriteria.getPageSize()); - query.setFirstResult(pageCriteria.getPageNumber()*pageCriteria.getPageSize()); + /** + * Get a page of results from the specified TypedQuery + * by using the given PageCriteria to limit the query + * results. The PageCriteria will override any size or + * offset already specified on the query. + * + * @param the type parameter + * @param query the query + * @param pageCriteria the page criteria + * @return the list + */ + public static List getResultPage(TypedQuery query, PageCriteria pageCriteria){ + query.setMaxResults(pageCriteria.getPageSize()); + query.setFirstResult(pageCriteria.getPageNumber()*pageCriteria.getPageSize()); - return query.getResultList(); - } + return query.getResultList(); + } public static T saveOrUpdate(I id, EntityManager entityManager, T entity) { T tmp = entityManager.merge(entity); diff --git a/openid-connect-common/src/test/java/org/mitre/data/AbstractPageOperationTemplateTest.java b/openid-connect-common/src/test/java/org/mitre/data/AbstractPageOperationTemplateTest.java index 46d8bf57eb..9bc11020fd 100644 --- a/openid-connect-common/src/test/java/org/mitre/data/AbstractPageOperationTemplateTest.java +++ b/openid-connect-common/src/test/java/org/mitre/data/AbstractPageOperationTemplateTest.java @@ -1,13 +1,13 @@ package org.mitre.data; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - import java.util.ArrayList; import java.util.Collection; import java.util.List; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -17,204 +17,200 @@ */ public class AbstractPageOperationTemplateTest { - @Before - public void setUp() throws Exception { - } - - @Test(timeout = 1000L) - public void execute_zeropages() { - CountingPageOperation op = new CountingPageOperation(0,Long.MAX_VALUE); - op.execute(); - - assertEquals(0L, op.counter); - } - - @Test(timeout = 1000L) - public void execute_singlepage() { - CountingPageOperation op = new CountingPageOperation(1,Long.MAX_VALUE); - op.execute(); - - assertEquals(10L, op.counter); - } - - @Test(timeout = 1000L) - public void execute_negpage() { - CountingPageOperation op = new CountingPageOperation(-1,Long.MAX_VALUE); - op.execute(); - - assertEquals(0L, op.counter); - } - - @Test(timeout = 1000L) - public void execute_npage(){ - int n = 7; - CountingPageOperation op = new CountingPageOperation(n,Long.MAX_VALUE); - op.execute(); - - assertEquals(n*10L, op.counter); - } - - @Test(timeout = 1000L) - public void execute_nullpage(){ - CountingPageOperation op = new NullPageCountingPageOperation(Integer.MAX_VALUE, Long.MAX_VALUE); - op.execute(); - - assertEquals(0L, op.getCounter()); - } - - @Test(timeout = 1000L) - public void execute_emptypage(){ - CountingPageOperation op = new EmptyPageCountingPageOperation(Integer.MAX_VALUE, Long.MAX_VALUE); - op.execute(); - - assertEquals(0L, op.getCounter()); - } - - @Test(timeout = 1000L) - public void execute_zerotime(){ - CountingPageOperation op = new CountingPageOperation(Integer.MAX_VALUE,0L); - op.execute(); - - assertEquals(0L, op.getCounter()); - assertEquals(0L, op.getTimeToLastFetch()); - } - - /* - * This is a valid test however it is vulnerable to a race condition - * as such it is being ignored. - */ - @Test(timeout = 1000L) - @Ignore - public void execute_nonzerotime(){ - Long timeMillis = 200L; - CountingPageOperation op = new CountingPageOperation(Integer.MAX_VALUE,timeMillis); - op.execute(); - - assertFalse("last fetch time " + op.getTimeToLastFetch() + "" + - " and previous fetch time " + op.getTimeToPreviousFetch() + - " exceed max time" + timeMillis, - op.getTimeToLastFetch() > timeMillis - && op.getTimeToPreviousFetch() > timeMillis); - } - - @Test(timeout = 1000L) - public void execute_negtime(){ - Long timeMillis = -100L; - CountingPageOperation op = new CountingPageOperation(Integer.MAX_VALUE,timeMillis); - op.execute(); - - assertEquals(0L, op.getCounter()); - } - - @Test(timeout = 1000L) - public void execute_swallowException(){ - CountingPageOperation op = new EvenExceptionCountingPageOperation(1, 1000L); - op.execute(); - - assertTrue(op.isSwallowExceptions()); - assertEquals(5L, op.getCounter()); - } - - @Test(expected = IllegalStateException.class) - public void execute_noSwallowException(){ - CountingPageOperation op = new EvenExceptionCountingPageOperation(1, 1000L); - op.setSwallowExceptions(false); - - try { - op.execute(); - }finally { - assertEquals(1L, op.getCounter()); - } - } - - - private static class CountingPageOperation extends AbstractPageOperationTemplate{ - - private int currentPageFetch; - private int pageSize = 10; - private long counter = 0L; - private long startTime; - private long timeToLastFetch; - private long timeToPreviousFetch; - - private CountingPageOperation(int maxPages, long maxTime) { - super(maxPages, maxTime, "CountingPageOperation"); - startTime = System.currentTimeMillis(); - } - - @Override - public Collection fetchPage() { - timeToPreviousFetch = timeToLastFetch > 0 ? timeToLastFetch : 0; - timeToLastFetch = System.currentTimeMillis() - startTime; - - List page = new ArrayList(pageSize); - for(int i = 0; i < pageSize; i++ ) { - page.add("item " + currentPageFetch * pageSize + i); - } - currentPageFetch++; - return page; - } - - @Override - protected void doOperation(String item) { - counter++; - } - - public long getCounter() { - return counter; - } - - public long getTimeToLastFetch() { - return timeToLastFetch; - } - - public long getTimeToPreviousFetch() { - return timeToPreviousFetch; - } - - public long getStartTime(){ - return startTime; - } - } - - private static class NullPageCountingPageOperation extends CountingPageOperation { - private NullPageCountingPageOperation(int maxPages, long maxTime) { - super(maxPages, maxTime); - } - - @Override - public Collection fetchPage() { - return null; - } - } - - private static class EmptyPageCountingPageOperation extends CountingPageOperation { - private EmptyPageCountingPageOperation(int maxPages, long maxTime) { - super(maxPages, maxTime); - } - - @Override - public Collection fetchPage() { - return new ArrayList<>(0); - } - } - - private static class EvenExceptionCountingPageOperation extends CountingPageOperation { - - private int callCounter; - private EvenExceptionCountingPageOperation(int maxPages, long maxTime) { - super(maxPages, maxTime); - } - - @Override - protected void doOperation(String item) { - callCounter++; - if(callCounter%2 == 0){ - throw new IllegalStateException("even number items cannot be processed"); - } - - super.doOperation(item); - - } - } + @Before + public void setUp() throws Exception { + } + + @Test(timeout = 1000L) + public void execute_zeropages() { + CountingPageOperation op = new CountingPageOperation(0,Long.MAX_VALUE); + op.execute(); + + assertEquals(0L, op.counter); + } + + @Test(timeout = 1000L) + public void execute_singlepage() { + CountingPageOperation op = new CountingPageOperation(1,Long.MAX_VALUE); + op.execute(); + + assertEquals(10L, op.counter); + } + + @Test(timeout = 1000L) + public void execute_negpage() { + CountingPageOperation op = new CountingPageOperation(-1,Long.MAX_VALUE); + op.execute(); + + assertEquals(0L, op.counter); + } + + @Test(timeout = 1000L) + public void execute_npage(){ + int n = 7; + CountingPageOperation op = new CountingPageOperation(n,Long.MAX_VALUE); + op.execute(); + + assertEquals(n*10L, op.counter); + } + + @Test(timeout = 1000L) + public void execute_nullpage(){ + CountingPageOperation op = new NullPageCountingPageOperation(Integer.MAX_VALUE, Long.MAX_VALUE); + op.execute(); + + assertEquals(0L, op.getCounter()); + } + + @Test(timeout = 1000L) + public void execute_emptypage(){ + CountingPageOperation op = new EmptyPageCountingPageOperation(Integer.MAX_VALUE, Long.MAX_VALUE); + op.execute(); + + assertEquals(0L, op.getCounter()); + } + + @Test(timeout = 1000L) + public void execute_zerotime(){ + CountingPageOperation op = new CountingPageOperation(Integer.MAX_VALUE,0L); + op.execute(); + + assertEquals(0L, op.getCounter()); + assertEquals(0L, op.getTimeToLastFetch()); + } + + /* + * This is a valid test however it is vulnerable to a race condition + * as such it is being ignored. + */ + @Test(timeout = 1000L) + @Ignore + public void execute_nonzerotime(){ + Long timeMillis = 200L; + CountingPageOperation op = new CountingPageOperation(Integer.MAX_VALUE,timeMillis); + op.execute(); + + assertFalse("last fetch time " + op.getTimeToLastFetch() + "" + + " and previous fetch time " + op.getTimeToPreviousFetch() + + " exceed max time" + timeMillis, + op.getTimeToLastFetch() > timeMillis + && op.getTimeToPreviousFetch() > timeMillis); + } + + @Test(timeout = 1000L) + public void execute_negtime(){ + Long timeMillis = -100L; + CountingPageOperation op = new CountingPageOperation(Integer.MAX_VALUE,timeMillis); + op.execute(); + + assertEquals(0L, op.getCounter()); + } + + @Test(timeout = 1000L) + public void execute_swallowException(){ + CountingPageOperation op = new EvenExceptionCountingPageOperation(1, 1000L); + op.execute(); + + assertTrue(op.isSwallowExceptions()); + assertEquals(5L, op.getCounter()); + } + + @Test(expected = IllegalStateException.class) + public void execute_noSwallowException(){ + CountingPageOperation op = new EvenExceptionCountingPageOperation(1, 1000L); + op.setSwallowExceptions(false); + + try { + op.execute(); + }finally { + assertEquals(1L, op.getCounter()); + } + } + + + private static class CountingPageOperation extends AbstractPageOperationTemplate{ + + private int currentPageFetch; + private int pageSize = 10; + private long counter = 0L; + private long startTime; + private long timeToLastFetch; + private long timeToPreviousFetch; + + private CountingPageOperation(int maxPages, long maxTime) { + super(maxPages, maxTime, "CountingPageOperation"); + startTime = System.currentTimeMillis(); + } + + @Override + public Collection fetchPage() { + timeToPreviousFetch = timeToLastFetch > 0 ? timeToLastFetch : 0; + timeToLastFetch = System.currentTimeMillis() - startTime; + + List page = new ArrayList(pageSize); + for(int i = 0; i < pageSize; i++ ) { + page.add("item " + currentPageFetch * pageSize + i); + } + currentPageFetch++; + return page; + } + + @Override + protected void doOperation(String item) { + counter++; + } + + public long getCounter() { + return counter; + } + + public long getTimeToLastFetch() { + return timeToLastFetch; + } + + public long getTimeToPreviousFetch() { + return timeToPreviousFetch; + } + } + + private static class NullPageCountingPageOperation extends CountingPageOperation { + private NullPageCountingPageOperation(int maxPages, long maxTime) { + super(maxPages, maxTime); + } + + @Override + public Collection fetchPage() { + return null; + } + } + + private static class EmptyPageCountingPageOperation extends CountingPageOperation { + private EmptyPageCountingPageOperation(int maxPages, long maxTime) { + super(maxPages, maxTime); + } + + @Override + public Collection fetchPage() { + return new ArrayList<>(0); + } + } + + private static class EvenExceptionCountingPageOperation extends CountingPageOperation { + + private int callCounter; + private EvenExceptionCountingPageOperation(int maxPages, long maxTime) { + super(maxPages, maxTime); + } + + @Override + protected void doOperation(String item) { + callCounter++; + if(callCounter%2 == 0){ + throw new IllegalStateException("even number items cannot be processed"); + } + + super.doOperation(item); + + } + } } diff --git a/openid-connect-common/src/test/java/org/mitre/jose/TestJWKSetKeyStore.java b/openid-connect-common/src/test/java/org/mitre/jose/TestJWKSetKeyStore.java index 120fcb2a10..d894edddd8 100644 --- a/openid-connect-common/src/test/java/org/mitre/jose/TestJWKSetKeyStore.java +++ b/openid-connect-common/src/test/java/org/mitre/jose/TestJWKSetKeyStore.java @@ -50,35 +50,35 @@ public class TestJWKSetKeyStore { private String RSAkid = "rsa_1"; private JWK RSAjwk = new RSAKey( new Base64URL("oahUIoWw0K0usKNuOR6H4wkf4oBUXHTxRvgb48E-BVvxkeDNjbC4he8rUW" + - "cJoZmds2h7M70imEVhRU5djINXtqllXI4DFqcI1DgjT9LewND8MW2Krf3S" + - "psk_ZkoFnilakGygTwpZ3uesH-PFABNIUYpOiN15dsQRkgr0vEhxN92i2a" + - "sbOenSZeyaxziK72UwxrrKoExv6kc5twXTq4h-QChLOln0_mtUZwfsRaMS" + - "tPs6mS6XrgxnxbWhojf663tuEQueGC-FCMfra36C9knDFGzKsNa7LZK2dj" + - "YgyD3JR_MB_4NUJW_TqOQtwHYbxevoJArm-L5StowjzGy-_bq6Gw"), // n + "cJoZmds2h7M70imEVhRU5djINXtqllXI4DFqcI1DgjT9LewND8MW2Krf3S" + + "psk_ZkoFnilakGygTwpZ3uesH-PFABNIUYpOiN15dsQRkgr0vEhxN92i2a" + + "sbOenSZeyaxziK72UwxrrKoExv6kc5twXTq4h-QChLOln0_mtUZwfsRaMS" + + "tPs6mS6XrgxnxbWhojf663tuEQueGC-FCMfra36C9knDFGzKsNa7LZK2dj" + + "YgyD3JR_MB_4NUJW_TqOQtwHYbxevoJArm-L5StowjzGy-_bq6Gw"), // n new Base64URL("AQAB"), // e new Base64URL("kLdtIj6GbDks_ApCSTYQtelcNttlKiOyPzMrXHeI-yk1F7-kpDxY4-WY5N" + - "WV5KntaEeXS1j82E375xxhWMHXyvjYecPT9fpwR_M9gV8n9Hrh2anTpTD9" + - "3Dt62ypW3yDsJzBnTnrYu1iwWRgBKrEYY46qAZIrA2xAwnm2X7uGR1hghk" + - "qDp0Vqj3kbSCz1XyfCs6_LehBwtxHIyh8Ripy40p24moOAbgxVw3rxT_vl" + - "t3UVe4WO3JkJOzlpUf-KTVI2Ptgm-dARxTEtE-id-4OJr0h-K-VFs3VSnd" + - "VTIznSxfyrj8ILL6MG_Uv8YAu7VILSB3lOW085-4qE3DzgrTjgyQ"), // d + "WV5KntaEeXS1j82E375xxhWMHXyvjYecPT9fpwR_M9gV8n9Hrh2anTpTD9" + + "3Dt62ypW3yDsJzBnTnrYu1iwWRgBKrEYY46qAZIrA2xAwnm2X7uGR1hghk" + + "qDp0Vqj3kbSCz1XyfCs6_LehBwtxHIyh8Ripy40p24moOAbgxVw3rxT_vl" + + "t3UVe4WO3JkJOzlpUf-KTVI2Ptgm-dARxTEtE-id-4OJr0h-K-VFs3VSnd" + + "VTIznSxfyrj8ILL6MG_Uv8YAu7VILSB3lOW085-4qE3DzgrTjgyQ"), // d KeyUse.ENCRYPTION, null, JWEAlgorithm.RSA_OAEP, RSAkid, null, null, null); private String RSAkid_rsa2 = "rsa_2"; private JWK RSAjwk_rsa2 = new RSAKey( new Base64URL("oahUIoWw0K0usKNuOR6H4wkf4oBUXHTxRvgb48E-BVvxkeDNjbC4he8rUW" + - "cJoZmds2h7M70imEVhRU5djINXtqllXI4DFqcI1DgjT9LewND8MW2Krf3S" + - "psk_ZkoFnilakGygTwpZ3uesH-PFABNIUYpOiN15dsQRkgr0vEhxN92i2a" + - "sbOenSZeyaxziK72UwxrrKoExv6kc5twXTq4h-QChLOln0_mtUZwfsRaMS" + - "tPs6mS6XrgxnxbWhojf663tuEQueGC-FCMfra36C9knDFGzKsNa7LZK2dj" + - "YgyD3JR_MB_4NUJW_TqOQtwHYbxevoJArm-L5StowjzGy-_bq6Gw"), // n + "cJoZmds2h7M70imEVhRU5djINXtqllXI4DFqcI1DgjT9LewND8MW2Krf3S" + + "psk_ZkoFnilakGygTwpZ3uesH-PFABNIUYpOiN15dsQRkgr0vEhxN92i2a" + + "sbOenSZeyaxziK72UwxrrKoExv6kc5twXTq4h-QChLOln0_mtUZwfsRaMS" + + "tPs6mS6XrgxnxbWhojf663tuEQueGC-FCMfra36C9knDFGzKsNa7LZK2dj" + + "YgyD3JR_MB_4NUJW_TqOQtwHYbxevoJArm-L5StowjzGy-_bq6Gw"), // n new Base64URL("AQAB"), // e new Base64URL("kLdtIj6GbDks_ApCSTYQtelcNttlKiOyPzMrXHeI-yk1F7-kpDxY4-WY5N" + - "WV5KntaEeXS1j82E375xxhWMHXyvjYecPT9fpwR_M9gV8n9Hrh2anTpTD9" + - "3Dt62ypW3yDsJzBnTnrYu1iwWRgBKrEYY46qAZIrA2xAwnm2X7uGR1hghk" + - "qDp0Vqj3kbSCz1XyfCs6_LehBwtxHIyh8Ripy40p24moOAbgxVw3rxT_vl" + - "t3UVe4WO3JkJOzlpUf-KTVI2Ptgm-dARxTEtE-id-4OJr0h-K-VFs3VSnd" + - "VTIznSxfyrj8ILL6MG_Uv8YAu7VILSB3lOW085-4qE3DzgrTjgyQ"), // d + "WV5KntaEeXS1j82E375xxhWMHXyvjYecPT9fpwR_M9gV8n9Hrh2anTpTD9" + + "3Dt62ypW3yDsJzBnTnrYu1iwWRgBKrEYY46qAZIrA2xAwnm2X7uGR1hghk" + + "qDp0Vqj3kbSCz1XyfCs6_LehBwtxHIyh8Ripy40p24moOAbgxVw3rxT_vl" + + "t3UVe4WO3JkJOzlpUf-KTVI2Ptgm-dARxTEtE-id-4OJr0h-K-VFs3VSnd" + + "VTIznSxfyrj8ILL6MG_Uv8YAu7VILSB3lOW085-4qE3DzgrTjgyQ"), // d KeyUse.ENCRYPTION, null, JWEAlgorithm.RSA1_5, RSAkid_rsa2, null, null, null); diff --git a/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java b/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java index fca1d4a24d..06f399f094 100644 --- a/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java +++ b/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java @@ -65,15 +65,15 @@ */ public class TestDefaultJWTEncryptionAndDecryptionService { - - private static Logger logger = LoggerFactory.getLogger(TestDefaultJWTEncryptionAndDecryptionService.class); + + private static Logger logger = LoggerFactory.getLogger(TestDefaultJWTEncryptionAndDecryptionService.class); private String plainText = "The true sign of intelligence is not knowledge but imagination."; private String issuer = "www.example.net"; private String subject = "example_user"; private JWTClaimsSet claimsSet = null; - + @Rule public ExpectedException exception = ExpectedException.none(); @@ -93,35 +93,35 @@ public class TestDefaultJWTEncryptionAndDecryptionService { private String RSAkid = "rsa321"; private JWK RSAjwk = new RSAKey( new Base64URL("oahUIoWw0K0usKNuOR6H4wkf4oBUXHTxRvgb48E-BVvxkeDNjbC4he8rUW" + - "cJoZmds2h7M70imEVhRU5djINXtqllXI4DFqcI1DgjT9LewND8MW2Krf3S" + - "psk_ZkoFnilakGygTwpZ3uesH-PFABNIUYpOiN15dsQRkgr0vEhxN92i2a" + - "sbOenSZeyaxziK72UwxrrKoExv6kc5twXTq4h-QChLOln0_mtUZwfsRaMS" + - "tPs6mS6XrgxnxbWhojf663tuEQueGC-FCMfra36C9knDFGzKsNa7LZK2dj" + - "YgyD3JR_MB_4NUJW_TqOQtwHYbxevoJArm-L5StowjzGy-_bq6Gw"), // n + "cJoZmds2h7M70imEVhRU5djINXtqllXI4DFqcI1DgjT9LewND8MW2Krf3S" + + "psk_ZkoFnilakGygTwpZ3uesH-PFABNIUYpOiN15dsQRkgr0vEhxN92i2a" + + "sbOenSZeyaxziK72UwxrrKoExv6kc5twXTq4h-QChLOln0_mtUZwfsRaMS" + + "tPs6mS6XrgxnxbWhojf663tuEQueGC-FCMfra36C9knDFGzKsNa7LZK2dj" + + "YgyD3JR_MB_4NUJW_TqOQtwHYbxevoJArm-L5StowjzGy-_bq6Gw"), // n new Base64URL("AQAB"), // e new Base64URL("kLdtIj6GbDks_ApCSTYQtelcNttlKiOyPzMrXHeI-yk1F7-kpDxY4-WY5N" + - "WV5KntaEeXS1j82E375xxhWMHXyvjYecPT9fpwR_M9gV8n9Hrh2anTpTD9" + - "3Dt62ypW3yDsJzBnTnrYu1iwWRgBKrEYY46qAZIrA2xAwnm2X7uGR1hghk" + - "qDp0Vqj3kbSCz1XyfCs6_LehBwtxHIyh8Ripy40p24moOAbgxVw3rxT_vl" + - "t3UVe4WO3JkJOzlpUf-KTVI2Ptgm-dARxTEtE-id-4OJr0h-K-VFs3VSnd" + - "VTIznSxfyrj8ILL6MG_Uv8YAu7VILSB3lOW085-4qE3DzgrTjgyQ"), // d + "WV5KntaEeXS1j82E375xxhWMHXyvjYecPT9fpwR_M9gV8n9Hrh2anTpTD9" + + "3Dt62ypW3yDsJzBnTnrYu1iwWRgBKrEYY46qAZIrA2xAwnm2X7uGR1hghk" + + "qDp0Vqj3kbSCz1XyfCs6_LehBwtxHIyh8Ripy40p24moOAbgxVw3rxT_vl" + + "t3UVe4WO3JkJOzlpUf-KTVI2Ptgm-dARxTEtE-id-4OJr0h-K-VFs3VSnd" + + "VTIznSxfyrj8ILL6MG_Uv8YAu7VILSB3lOW085-4qE3DzgrTjgyQ"), // d KeyUse.ENCRYPTION, null, JWEAlgorithm.RSA_OAEP, RSAkid, null, null, null); private String RSAkid_2 = "rsa3210"; private JWK RSAjwk_2 = new RSAKey( new Base64URL("oahUIoWw0K0usKNuOR6H4wkf4oBUXHTxRvgb48E-BVvxkeDNjbC4he8rUW" + - "cJoZmds2h7M70imEVhRU5djINXtqllXI4DFqcI1DgjT9LewND8MW2Krf3S" + - "psk_ZkoFnilakGygTwpZ3uesH-PFABNIUYpOiN15dsQRkgr0vEhxN92i2a" + - "sbOenSZeyaxziK72UwxrrKoExv6kc5twXTq4h-QChLOln0_mtUZwfsRaMS" + - "tPs6mS6XrgxnxbWhojf663tuEQueGC-FCMfra36C9knDFGzKsNa7LZK2dj" + - "YgyD3JR_MB_4NUJW_TqOQtwHYbxevoJArm-L5StowjzGy-_bq6Gw"), // n + "cJoZmds2h7M70imEVhRU5djINXtqllXI4DFqcI1DgjT9LewND8MW2Krf3S" + + "psk_ZkoFnilakGygTwpZ3uesH-PFABNIUYpOiN15dsQRkgr0vEhxN92i2a" + + "sbOenSZeyaxziK72UwxrrKoExv6kc5twXTq4h-QChLOln0_mtUZwfsRaMS" + + "tPs6mS6XrgxnxbWhojf663tuEQueGC-FCMfra36C9knDFGzKsNa7LZK2dj" + + "YgyD3JR_MB_4NUJW_TqOQtwHYbxevoJArm-L5StowjzGy-_bq6Gw"), // n new Base64URL("AQAB"), // e new Base64URL("kLdtIj6GbDks_ApCSTYQtelcNttlKiOyPzMrXHeI-yk1F7-kpDxY4-WY5N" + - "WV5KntaEeXS1j82E375xxhWMHXyvjYecPT9fpwR_M9gV8n9Hrh2anTpTD9" + - "3Dt62ypW3yDsJzBnTnrYu1iwWRgBKrEYY46qAZIrA2xAwnm2X7uGR1hghk" + - "qDp0Vqj3kbSCz1XyfCs6_LehBwtxHIyh8Ripy40p24moOAbgxVw3rxT_vl" + - "t3UVe4WO3JkJOzlpUf-KTVI2Ptgm-dARxTEtE-id-4OJr0h-K-VFs3VSnd" + - "VTIznSxfyrj8ILL6MG_Uv8YAu7VILSB3lOW085-4qE3DzgrTjgyQ"), // d + "WV5KntaEeXS1j82E375xxhWMHXyvjYecPT9fpwR_M9gV8n9Hrh2anTpTD9" + + "3Dt62ypW3yDsJzBnTnrYu1iwWRgBKrEYY46qAZIrA2xAwnm2X7uGR1hghk" + + "qDp0Vqj3kbSCz1XyfCs6_LehBwtxHIyh8Ripy40p24moOAbgxVw3rxT_vl" + + "t3UVe4WO3JkJOzlpUf-KTVI2Ptgm-dARxTEtE-id-4OJr0h-K-VFs3VSnd" + + "VTIznSxfyrj8ILL6MG_Uv8YAu7VILSB3lOW085-4qE3DzgrTjgyQ"), // d KeyUse.ENCRYPTION, null, JWEAlgorithm.RSA1_5, RSAkid_2, null, null, null); private String AESkid = "aes123"; @@ -165,9 +165,9 @@ public void prepare() throws NoSuchAlgorithmException, InvalidKeySpecException, service_4 = new DefaultJWTEncryptionAndDecryptionService(keys_4); claimsSet = new JWTClaimsSet.Builder() - .issuer(issuer) - .subject(subject) - .build(); + .issuer(issuer) + .subject(subject) + .build(); // Key Store @@ -186,7 +186,7 @@ public void decrypt_RSA() throws ParseException, NoSuchAlgorithmException { Assume.assumeTrue(JCASupport.isSupported(JWEAlgorithm.RSA_OAEP) // check for algorithm support && JCASupport.isSupported(EncryptionMethod.A256GCM) && Cipher.getMaxAllowedKeyLength("RC5") >= 256); // check for unlimited crypto strength - + service.setDefaultDecryptionKeyId(RSAkid); service.setDefaultEncryptionKeyId(RSAkid); @@ -207,7 +207,7 @@ public void encryptThenDecrypt_RSA() throws ParseException, NoSuchAlgorithmExcep Assume.assumeTrue(JCASupport.isSupported(JWEAlgorithm.RSA_OAEP) // check for algorithm support && JCASupport.isSupported(EncryptionMethod.A256GCM) && Cipher.getMaxAllowedKeyLength("RC5") >= 256); // check for unlimited crypto strength - + service.setDefaultDecryptionKeyId(RSAkid); service.setDefaultEncryptionKeyId(RSAkid); @@ -235,11 +235,11 @@ public void encryptThenDecrypt_RSA() throws ParseException, NoSuchAlgorithmExcep // The same as encryptThenDecrypt_RSA() but relies on the key from the map @Test public void encryptThenDecrypt_nullID() throws ParseException, NoSuchAlgorithmException { - + Assume.assumeTrue(JCASupport.isSupported(JWEAlgorithm.RSA_OAEP) // check for algorithm support && JCASupport.isSupported(EncryptionMethod.A256GCM) && Cipher.getMaxAllowedKeyLength("RC5") >= 256); // check for unlimited crypto strength - + service.setDefaultDecryptionKeyId(null); service.setDefaultEncryptionKeyId(null); @@ -272,7 +272,7 @@ public void encrypt_nullID_oneKey() throws NoSuchAlgorithmException { && Cipher.getMaxAllowedKeyLength("RC5") >= 256); // check for unlimited crypto strength exception.expect(IllegalStateException.class); - + service_2.setDefaultEncryptionKeyId(null); assertEquals(null, service_2.getDefaultEncryptionKeyId()); @@ -291,10 +291,10 @@ public void decrypt_nullID() throws ParseException, NoSuchAlgorithmException { Assume.assumeTrue(JCASupport.isSupported(JWEAlgorithm.RSA_OAEP) // check for algorithm support && JCASupport.isSupported(EncryptionMethod.A256GCM) && Cipher.getMaxAllowedKeyLength("RC5") >= 256); // check for unlimited crypto strength - + exception.expect(IllegalStateException.class); - + service_2.setDefaultEncryptionKeyId(RSAkid); service_2.setDefaultDecryptionKeyId(null); diff --git a/openid-connect-common/src/test/java/org/mitre/oauth2/model/ClientDetailsEntityTest.java b/openid-connect-common/src/test/java/org/mitre/oauth2/model/ClientDetailsEntityTest.java index a93aba7796..1f4887fb40 100644 --- a/openid-connect-common/src/test/java/org/mitre/oauth2/model/ClientDetailsEntityTest.java +++ b/openid-connect-common/src/test/java/org/mitre/oauth2/model/ClientDetailsEntityTest.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.model; diff --git a/openid-connect-common/src/test/java/org/mitre/oauth2/model/RegisteredClientTest.java b/openid-connect-common/src/test/java/org/mitre/oauth2/model/RegisteredClientTest.java index c00b8a3d36..3473128033 100644 --- a/openid-connect-common/src/test/java/org/mitre/oauth2/model/RegisteredClientTest.java +++ b/openid-connect-common/src/test/java/org/mitre/oauth2/model/RegisteredClientTest.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.model; diff --git a/openid-connect-common/src/test/java/org/mitre/openid/connect/ClientDetailsEntityJsonProcessorTest.java b/openid-connect-common/src/test/java/org/mitre/openid/connect/ClientDetailsEntityJsonProcessorTest.java index 93c80145d4..9e7df37d20 100644 --- a/openid-connect-common/src/test/java/org/mitre/openid/connect/ClientDetailsEntityJsonProcessorTest.java +++ b/openid-connect-common/src/test/java/org/mitre/openid/connect/ClientDetailsEntityJsonProcessorTest.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect; diff --git a/openid-connect-common/src/test/java/org/mitre/openid/connect/config/ConfigurationPropertiesBeanTest.java b/openid-connect-common/src/test/java/org/mitre/openid/connect/config/ConfigurationPropertiesBeanTest.java index 130caf399d..21f57504d2 100644 --- a/openid-connect-common/src/test/java/org/mitre/openid/connect/config/ConfigurationPropertiesBeanTest.java +++ b/openid-connect-common/src/test/java/org/mitre/openid/connect/config/ConfigurationPropertiesBeanTest.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.config; @@ -134,7 +134,7 @@ public void testCheckForHttpsIssuerHttpsTrueFlag() { } } - + @Test public void testShortTopbarTitle() { ConfigurationPropertiesBean bean = new ConfigurationPropertiesBean(); diff --git a/openid-connect-common/src/test/java/org/mitre/openid/connect/config/ServerConfigurationTest.java b/openid-connect-common/src/test/java/org/mitre/openid/connect/config/ServerConfigurationTest.java index 26c402eac9..8a4d6c51da 100644 --- a/openid-connect-common/src/test/java/org/mitre/openid/connect/config/ServerConfigurationTest.java +++ b/openid-connect-common/src/test/java/org/mitre/openid/connect/config/ServerConfigurationTest.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.config; diff --git a/openid-connect-server/src/main/java/org/mitre/discovery/view/WebfingerView.java b/openid-connect-server/src/main/java/org/mitre/discovery/view/WebfingerView.java index 0f254e5712..ef8a7f1e6d 100644 --- a/openid-connect-server/src/main/java/org/mitre/discovery/view/WebfingerView.java +++ b/openid-connect-server/src/main/java/org/mitre/discovery/view/WebfingerView.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.discovery.view; @@ -54,27 +54,27 @@ public class WebfingerView extends AbstractView { private static final Logger logger = LoggerFactory.getLogger(WebfingerView.class); private Gson gson = new GsonBuilder() - .setExclusionStrategies(new ExclusionStrategy() { - - @Override - public boolean shouldSkipField(FieldAttributes f) { - - return false; - } - - @Override - public boolean shouldSkipClass(Class clazz) { - // skip the JPA binding wrapper - if (clazz.equals(BeanPropertyBindingResult.class)) { - return true; - } - return false; - } - - }) - .serializeNulls() - .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") - .create(); + .setExclusionStrategies(new ExclusionStrategy() { + + @Override + public boolean shouldSkipField(FieldAttributes f) { + + return false; + } + + @Override + public boolean shouldSkipClass(Class clazz) { + // skip the JPA binding wrapper + if (clazz.equals(BeanPropertyBindingResult.class)) { + return true; + } + return false; + } + + }) + .serializeNulls() + .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") + .create(); @Override protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) { diff --git a/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java b/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java index 1c034924b4..0c2df3b060 100644 --- a/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java @@ -57,9 +57,9 @@ import com.nimbusds.jose.JWSAlgorithm; /** - * + * * Handle OpenID Connect Discovery. - * + * * @author jricher * */ @@ -109,7 +109,7 @@ public String webfinger(@RequestParam("resource") String resource, @RequestParam if (!Strings.isNullOrEmpty(rel) && !rel.equals("http://openid.net/specs/connect/1.0/issuer")) { logger.warn("Responding to webfinger request for non-OIDC relation: " + rel); } - + if (!resource.equals(config.getIssuer())) { // it's not the issuer directly, need to check other methods @@ -291,16 +291,16 @@ OPTIONAL. JSON array containing a list of the JWS signing algorithms (alg values baseUrl = baseUrl.concat("/"); } - Collection serverSigningAlgs = signService.getAllSigningAlgsSupported(); - Collection clientSymmetricSigningAlgs = Lists.newArrayList(JWSAlgorithm.HS256, JWSAlgorithm.HS384, JWSAlgorithm.HS512); - Collection clientSymmetricAndAsymmetricSigningAlgs = Lists.newArrayList(JWSAlgorithm.HS256, JWSAlgorithm.HS384, JWSAlgorithm.HS512, - JWSAlgorithm.RS256, JWSAlgorithm.RS384, JWSAlgorithm.RS512, - JWSAlgorithm.ES256, JWSAlgorithm.ES384, JWSAlgorithm.ES512, + signService.getAllSigningAlgsSupported(); + Lists.newArrayList(JWSAlgorithm.HS256, JWSAlgorithm.HS384, JWSAlgorithm.HS512); + Collection clientSymmetricAndAsymmetricSigningAlgs = Lists.newArrayList(JWSAlgorithm.HS256, JWSAlgorithm.HS384, JWSAlgorithm.HS512, + JWSAlgorithm.RS256, JWSAlgorithm.RS384, JWSAlgorithm.RS512, + JWSAlgorithm.ES256, JWSAlgorithm.ES384, JWSAlgorithm.ES512, JWSAlgorithm.PS256, JWSAlgorithm.PS384, JWSAlgorithm.PS512); - Collection clientSymmetricAndAsymmetricSigningAlgsWithNone = Lists.newArrayList(JWSAlgorithm.HS256, JWSAlgorithm.HS384, JWSAlgorithm.HS512, - JWSAlgorithm.RS256, JWSAlgorithm.RS384, JWSAlgorithm.RS512, - JWSAlgorithm.ES256, JWSAlgorithm.ES384, JWSAlgorithm.ES512, - JWSAlgorithm.PS256, JWSAlgorithm.PS384, JWSAlgorithm.PS512, + Collection clientSymmetricAndAsymmetricSigningAlgsWithNone = Lists.newArrayList(JWSAlgorithm.HS256, JWSAlgorithm.HS384, JWSAlgorithm.HS512, + JWSAlgorithm.RS256, JWSAlgorithm.RS384, JWSAlgorithm.RS512, + JWSAlgorithm.ES256, JWSAlgorithm.ES384, JWSAlgorithm.ES512, + JWSAlgorithm.PS256, JWSAlgorithm.PS384, JWSAlgorithm.PS512, Algorithm.NONE); ArrayList grantTypes = Lists.newArrayList("authorization_code", "implicit", "urn:ietf:params:oauth:grant-type:jwt-bearer", "client_credentials", "urn:ietf:params:oauth:grant_type:redelegate", "urn:ietf:params:oauth:grant-type:device_code"); @@ -369,7 +369,7 @@ OPTIONAL. JSON array containing a list of the JWS signing algorithms (alg values m.put("code_challenge_methods_supported", Lists.newArrayList(PKCEAlgorithm.plain.getName(), PKCEAlgorithm.S256.getName())); m.put("device_authorization_endpoint", DeviceEndpoint.URL); - + model.addAttribute(JsonEntityView.ENTITY, m); return JsonEntityView.VIEWNAME; diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/assertion/AssertionOAuth2RequestFactory.java b/openid-connect-server/src/main/java/org/mitre/oauth2/assertion/AssertionOAuth2RequestFactory.java index aa20c35076..567c8c64fb 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/assertion/AssertionOAuth2RequestFactory.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/assertion/AssertionOAuth2RequestFactory.java @@ -25,7 +25,7 @@ /** * Take in an assertion and token request and generate an OAuth2Request from it, including scopes and other important components - * + * * @author jricher * */ diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/assertion/impl/DirectCopyRequestFactory.java b/openid-connect-server/src/main/java/org/mitre/oauth2/assertion/impl/DirectCopyRequestFactory.java index 97e52a89de..6dae9f7b94 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/assertion/impl/DirectCopyRequestFactory.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/assertion/impl/DirectCopyRequestFactory.java @@ -18,7 +18,6 @@ package org.mitre.oauth2.assertion.impl; import java.text.ParseException; -import java.util.List; import java.util.Set; import org.mitre.oauth2.assertion.AssertionOAuth2RequestFactory; @@ -33,10 +32,10 @@ /** * Takes an assertion from a trusted source, looks for the fields: - * + * * - scope, space-separated list of strings * - aud, array of audience IDs - * + * * @author jricher * */ @@ -51,14 +50,14 @@ public OAuth2Request createOAuth2Request(ClientDetails client, TokenRequest toke try { JWTClaimsSet claims = assertion.getJWTClaimsSet(); Set scope = OAuth2Utils.parseParameterList(claims.getStringClaim("scope")); - + Set resources = Sets.newHashSet(claims.getAudience()); - + return new OAuth2Request(tokenRequest.getRequestParameters(), client.getClientId(), client.getAuthorities(), true, scope, resources, null, null, null); } catch (ParseException e) { return null; } - + } } diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/exception/AuthorizationPendingException.java b/openid-connect-server/src/main/java/org/mitre/oauth2/exception/AuthorizationPendingException.java index e2ea2f71b1..b620c9b5dc 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/exception/AuthorizationPendingException.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/exception/AuthorizationPendingException.java @@ -33,7 +33,7 @@ public AuthorizationPendingException(String msg) { } /** - * + * */ private static final long serialVersionUID = -7078098692596870940L; @@ -45,6 +45,6 @@ public String getOAuth2ErrorCode() { return "authorization_pending"; } - - + + } diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/exception/DeviceCodeExpiredException.java b/openid-connect-server/src/main/java/org/mitre/oauth2/exception/DeviceCodeExpiredException.java index 6444f184a4..8a49caf0f1 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/exception/DeviceCodeExpiredException.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/exception/DeviceCodeExpiredException.java @@ -33,7 +33,7 @@ public DeviceCodeExpiredException(String msg) { } /** - * + * */ private static final long serialVersionUID = -7078098692596870940L; diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/exception/DuplicateClientIdException.java b/openid-connect-server/src/main/java/org/mitre/oauth2/exception/DuplicateClientIdException.java index 71a4733cca..c102785c78 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/exception/DuplicateClientIdException.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/exception/DuplicateClientIdException.java @@ -23,7 +23,7 @@ public DuplicateClientIdException(String clientId) { } /** - * + * */ private static final long serialVersionUID = 1L; diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthenticationHolderRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthenticationHolderRepository.java index b0de267645..48e0b6b534 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthenticationHolderRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthenticationHolderRepository.java @@ -70,15 +70,15 @@ public AuthenticationHolderEntity save(AuthenticationHolderEntity a) { @Override @Transactional(value="defaultTransactionManager") public List getOrphanedAuthenticationHolders() { - DefaultPageCriteria pageCriteria = new DefaultPageCriteria(0,MAXEXPIREDRESULTS); - return getOrphanedAuthenticationHolders(pageCriteria); + DefaultPageCriteria pageCriteria = new DefaultPageCriteria(0,MAXEXPIREDRESULTS); + return getOrphanedAuthenticationHolders(pageCriteria); } - @Override - @Transactional(value="defaultTransactionManager") - public List getOrphanedAuthenticationHolders(PageCriteria pageCriteria) { - TypedQuery query = manager.createNamedQuery(AuthenticationHolderEntity.QUERY_GET_UNUSED, AuthenticationHolderEntity.class); - return JpaUtil.getResultPage(query, pageCriteria); - } + @Override + @Transactional(value="defaultTransactionManager") + public List getOrphanedAuthenticationHolders(PageCriteria pageCriteria) { + TypedQuery query = manager.createNamedQuery(AuthenticationHolderEntity.QUERY_GET_UNUSED, AuthenticationHolderEntity.class); + return JpaUtil.getResultPage(query, pageCriteria); + } } diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthorizationCodeRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthorizationCodeRepository.java index 9cdde90866..5866b9162e 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthorizationCodeRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthorizationCodeRepository.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.repository.impl; @@ -35,7 +35,7 @@ /** * JPA AuthorizationCodeRepository implementation. - * + * * @author aanganes * */ @@ -92,12 +92,12 @@ public Collection getExpiredCodes() { } - @Override - public Collection getExpiredCodes(PageCriteria pageCriteria) { - TypedQuery query = manager.createNamedQuery(AuthorizationCodeEntity.QUERY_EXPIRATION_BY_DATE, AuthorizationCodeEntity.class); - query.setParameter(AuthorizationCodeEntity.PARAM_DATE, new Date()); // this gets anything that's already expired - return JpaUtil.getResultPage(query, pageCriteria); - } + @Override + public Collection getExpiredCodes(PageCriteria pageCriteria) { + TypedQuery query = manager.createNamedQuery(AuthorizationCodeEntity.QUERY_EXPIRATION_BY_DATE, AuthorizationCodeEntity.class); + query.setParameter(AuthorizationCodeEntity.PARAM_DATE, new Date()); // this gets anything that's already expired + return JpaUtil.getResultPage(query, pageCriteria); + } diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaDeviceCodeRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaDeviceCodeRepository.java index 91f34dfccf..7f15d021b6 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaDeviceCodeRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaDeviceCodeRepository.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.repository.impl; @@ -24,8 +24,6 @@ import java.util.Collection; import java.util.Date; -import java.util.LinkedHashSet; -import java.util.Set; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java index 3be11b3767..8624d4184f 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java @@ -52,7 +52,7 @@ public class JpaOAuth2TokenRepository implements OAuth2TokenRepository { private static final int MAXEXPIREDRESULTS = 1000; - + private static final Logger logger = LoggerFactory.getLogger(JpaOAuth2TokenRepository.class); @PersistenceContext(unitName="defaultPersistenceUnit") @@ -191,29 +191,29 @@ public List getRefreshTokensForClient(ClientDetailsEnt @Override public Set getAllExpiredAccessTokens() { - DefaultPageCriteria pageCriteria = new DefaultPageCriteria(0, MAXEXPIREDRESULTS); - return getAllExpiredAccessTokens(pageCriteria); + DefaultPageCriteria pageCriteria = new DefaultPageCriteria(0, MAXEXPIREDRESULTS); + return getAllExpiredAccessTokens(pageCriteria); } - @Override - public Set getAllExpiredAccessTokens(PageCriteria pageCriteria) { - TypedQuery query = manager.createNamedQuery(OAuth2AccessTokenEntity.QUERY_EXPIRED_BY_DATE, OAuth2AccessTokenEntity.class); - query.setParameter(OAuth2AccessTokenEntity.PARAM_DATE, new Date()); - return new LinkedHashSet<>(JpaUtil.getResultPage(query, pageCriteria)); - } + @Override + public Set getAllExpiredAccessTokens(PageCriteria pageCriteria) { + TypedQuery query = manager.createNamedQuery(OAuth2AccessTokenEntity.QUERY_EXPIRED_BY_DATE, OAuth2AccessTokenEntity.class); + query.setParameter(OAuth2AccessTokenEntity.PARAM_DATE, new Date()); + return new LinkedHashSet<>(JpaUtil.getResultPage(query, pageCriteria)); + } @Override public Set getAllExpiredRefreshTokens() { - DefaultPageCriteria pageCriteria = new DefaultPageCriteria(0, MAXEXPIREDRESULTS); - return getAllExpiredRefreshTokens(pageCriteria); + DefaultPageCriteria pageCriteria = new DefaultPageCriteria(0, MAXEXPIREDRESULTS); + return getAllExpiredRefreshTokens(pageCriteria); } - @Override - public Set getAllExpiredRefreshTokens(PageCriteria pageCriteria) { - TypedQuery query = manager.createNamedQuery(OAuth2RefreshTokenEntity.QUERY_EXPIRED_BY_DATE, OAuth2RefreshTokenEntity.class); - query.setParameter(OAuth2AccessTokenEntity.PARAM_DATE, new Date()); - return new LinkedHashSet<>(JpaUtil.getResultPage(query,pageCriteria)); - } + @Override + public Set getAllExpiredRefreshTokens(PageCriteria pageCriteria) { + TypedQuery query = manager.createNamedQuery(OAuth2RefreshTokenEntity.QUERY_EXPIRED_BY_DATE, OAuth2RefreshTokenEntity.class); + query.setParameter(OAuth2AccessTokenEntity.PARAM_DATE, new Date()); + return new LinkedHashSet<>(JpaUtil.getResultPage(query,pageCriteria)); + } @@ -276,7 +276,7 @@ public void clearDuplicateRefreshTokens() { } } - + @Override public List getAccessTokensForApprovedSite(ApprovedSite approvedSite) { TypedQuery queryA = manager.createNamedQuery(OAuth2AccessTokenEntity.QUERY_BY_APPROVED_SITE, OAuth2AccessTokenEntity.class); diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaSystemScopeRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaSystemScopeRepository.java index 23c829bbd7..b420b57bf4 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaSystemScopeRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaSystemScopeRepository.java @@ -15,10 +15,13 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.repository.impl; +import static org.mitre.util.jpa.JpaUtil.getSingleResult; +import static org.mitre.util.jpa.JpaUtil.saveOrUpdate; + import java.util.LinkedHashSet; import java.util.Set; @@ -31,9 +34,6 @@ import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; -import static org.mitre.util.jpa.JpaUtil.getSingleResult; -import static org.mitre.util.jpa.JpaUtil.saveOrUpdate; - /** * @author jricher * diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/BlacklistAwareRedirectResolver.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/BlacklistAwareRedirectResolver.java index c64c9cc739..2cc571a906 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/BlacklistAwareRedirectResolver.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/BlacklistAwareRedirectResolver.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.service.impl; @@ -31,10 +31,10 @@ import com.google.common.base.Strings; /** - * + * * A redirect resolver that knows how to check against the blacklisted URIs * for forbidden values. Can be configured to do strict string matching also. - * + * * @author jricher * */ @@ -46,7 +46,7 @@ public class BlacklistAwareRedirectResolver extends DefaultRedirectResolver { @Autowired private ConfigurationPropertiesBean config; - + private boolean strictMatch = false; /* (non-Javadoc) @@ -94,7 +94,7 @@ public boolean isStrictMatch() { /** * Set this to true to require exact string matches for all redirect URIs. (Default is false) - * + * * @param strictMatch the strictMatch to set */ public void setStrictMatch(boolean strictMatch) { diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java index ecd4c1684a..8020de7a63 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java @@ -24,7 +24,6 @@ import org.mitre.data.AbstractPageOperationTemplate; import org.mitre.oauth2.model.AuthenticationHolderEntity; -import org.mitre.oauth2.model.AuthorizationCodeEntity; import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.model.DeviceCode; import org.mitre.oauth2.repository.impl.DeviceCodeRepository; @@ -41,24 +40,24 @@ */ @Service("defaultDeviceCodeService") public class DefaultDeviceCodeService implements DeviceCodeService { - + @Autowired private DeviceCodeRepository repository; - + /* (non-Javadoc) * @see org.mitre.oauth2.service.DeviceCodeService#save(org.mitre.oauth2.model.DeviceCode) */ @Override public DeviceCode createNewDeviceCode(String deviceCode, String userCode, Set requestedScopes, ClientDetailsEntity client, Map parameters) { - + DeviceCode dc = new DeviceCode(deviceCode, userCode, requestedScopes, client.getClientId(), parameters); - + if (client.getDeviceCodeValiditySeconds() != null) { dc.setExpiration(new Date(System.currentTimeMillis() + client.getDeviceCodeValiditySeconds() * 1000L)); } - + dc.setApproved(false); - + return repository.save(dc); } @@ -76,12 +75,12 @@ public DeviceCode lookUpByUserCode(String userCode) { @Override public DeviceCode approveDeviceCode(DeviceCode dc, OAuth2Authentication auth) { DeviceCode found = repository.getById(dc.getId()); - + found.setApproved(true); - + AuthenticationHolderEntity authHolder = new AuthenticationHolderEntity(); authHolder.setAuthentication(auth); - + found.setAuthenticationHolder(authHolder); return repository.save(found); @@ -93,10 +92,10 @@ public DeviceCode approveDeviceCode(DeviceCode dc, OAuth2Authentication auth) { @Override public DeviceCode consumeDeviceCode(String deviceCode, ClientDetails client) { DeviceCode found = repository.getByDeviceCode(deviceCode); - + // make sure it's not used twice repository.remove(found); - + if (found.getClientId().equals(client.getClientId())) { // make sure the client matches, if so, we're good return found; @@ -104,7 +103,7 @@ public DeviceCode consumeDeviceCode(String deviceCode, ClientDetails client) { // if the clients don't match, pretend the code wasn't found return null; } - + } /* (non-Javadoc) @@ -113,18 +112,18 @@ public DeviceCode consumeDeviceCode(String deviceCode, ClientDetails client) { @Override @Transactional(value="defaultTransactionManager") public void clearExpiredDeviceCodes() { - - new AbstractPageOperationTemplate("clearExpiredDeviceCodes"){ - @Override - public Collection fetchPage() { - return repository.getExpiredCodes(); - } - - @Override - protected void doOperation(DeviceCode item) { - repository.remove(item); - } - }.execute(); + + new AbstractPageOperationTemplate("clearExpiredDeviceCodes"){ + @Override + public Collection fetchPage() { + return repository.getExpiredCodes(); + } + + @Override + protected void doOperation(DeviceCode item) { + repository.remove(item); + } + }.execute(); } } diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultIntrospectionResultAssembler.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultIntrospectionResultAssembler.java index f7e2ac44bc..40314158bb 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultIntrospectionResultAssembler.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultIntrospectionResultAssembler.java @@ -16,6 +16,8 @@ *******************************************************************************/ package org.mitre.oauth2.service.impl; +import static com.google.common.collect.Maps.newLinkedHashMap; + import java.text.ParseException; import java.util.Map; import java.util.Set; @@ -33,8 +35,6 @@ import com.google.common.base.Joiner; import com.google.common.collect.Sets; -import static com.google.common.collect.Maps.newLinkedHashMap; - /** * Default implementation of the {@link IntrospectionResultAssembler} interface. */ diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2AuthorizationCodeService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2AuthorizationCodeService.java index 59806caa2f..d9589bf93e 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2AuthorizationCodeService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2AuthorizationCodeService.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.service.impl; @@ -39,7 +39,7 @@ /** * Database-backed, random-value authorization code service implementation. - * + * * @author aanganes * */ @@ -61,7 +61,7 @@ public class DefaultOAuth2AuthorizationCodeService implements AuthorizationCodeS /** * Generate a random authorization code and create an AuthorizationCodeEntity, * which will be stored in the repository. - * + * * @param authentication the authentication of the current user, to be retrieved when the * code is consumed * @return the authorization code @@ -90,7 +90,7 @@ public String createAuthorizationCode(OAuth2Authentication authentication) { * Match the provided string to an AuthorizationCodeEntity. If one is found, return * the authentication associated with the code. If one is not found, throw an * InvalidGrantException. - * + * * @param code the authorization code * @return the authentication that made the original request * @throws InvalidGrantException, if an AuthorizationCodeEntity is not found with the given value @@ -117,17 +117,17 @@ public OAuth2Authentication consumeAuthorizationCode(String code) throws Invalid @Transactional(value="defaultTransactionManager") public void clearExpiredAuthorizationCodes() { - new AbstractPageOperationTemplate("clearExpiredAuthorizationCodes"){ - @Override - public Collection fetchPage() { - return repository.getExpiredCodes(); - } - - @Override - protected void doOperation(AuthorizationCodeEntity item) { - repository.remove(item); - } - }.execute(); + new AbstractPageOperationTemplate("clearExpiredAuthorizationCodes"){ + @Override + public Collection fetchPage() { + return repository.getExpiredCodes(); + } + + @Override + protected void doOperation(AuthorizationCodeEntity item) { + repository.remove(item); + } + }.execute(); } /** diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ClientDetailsEntityService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ClientDetailsEntityService.java index 6b3fc94567..744b623a18 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ClientDetailsEntityService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ClientDetailsEntityService.java @@ -124,13 +124,13 @@ public ClientDetailsEntity saveNewClient(ClientDetailsEntity client) { if (Strings.isNullOrEmpty(client.getClientId())) { client = generateClientId(client); } - + // make sure that clients with the "refresh_token" grant type have the "offline_access" scope, and vice versa ensureRefreshTokenConsistency(client); // make sure we don't have both a JWKS and a JWKS URI ensureKeyConsistency(client); - + // check consistency when using HEART mode checkHeartMode(client); @@ -215,7 +215,7 @@ private void ensureRefreshTokenConsistency(ClientDetailsEntity client) { * - A redirect_uri must be registered with either authorization_code or implicit * - A key must be registered * - A client secret must not be generated - * - authorization_code and client_credentials must use the private_key authorization method + * - authorization_code and client_credentials must use the private_key authorization method * @param client */ private void checkHeartMode(ClientDetailsEntity client) { @@ -225,53 +225,53 @@ private void checkHeartMode(ClientDetailsEntity client) { if (client.getGrantTypes().contains("implicit") || client.getGrantTypes().contains("client_credentials")) { throw new IllegalArgumentException("[HEART mode] Incompatible grant types"); } - + // make sure we've got the right authentication method if (client.getTokenEndpointAuthMethod() == null || !client.getTokenEndpointAuthMethod().equals(AuthMethod.PRIVATE_KEY)) { throw new IllegalArgumentException("[HEART mode] Authorization code clients must use the private_key authentication method"); } - + // make sure we've got a redirect URI if (client.getRedirectUris().isEmpty()) { throw new IllegalArgumentException("[HEART mode] Authorization code clients must register at least one redirect URI"); } } - + if (client.getGrantTypes().contains("implicit")) { // make sure we don't have incompatible grant types if (client.getGrantTypes().contains("authorization_code") || client.getGrantTypes().contains("client_credentials") || client.getGrantTypes().contains("refresh_token")) { throw new IllegalArgumentException("[HEART mode] Incompatible grant types"); } - + // make sure we've got the right authentication method if (client.getTokenEndpointAuthMethod() == null || !client.getTokenEndpointAuthMethod().equals(AuthMethod.NONE)) { throw new IllegalArgumentException("[HEART mode] Implicit clients must use the none authentication method"); } - + // make sure we've got a redirect URI if (client.getRedirectUris().isEmpty()) { throw new IllegalArgumentException("[HEART mode] Implicit clients must register at least one redirect URI"); } } - + if (client.getGrantTypes().contains("client_credentials")) { // make sure we don't have incompatible grant types if (client.getGrantTypes().contains("authorization_code") || client.getGrantTypes().contains("implicit") || client.getGrantTypes().contains("refresh_token")) { throw new IllegalArgumentException("[HEART mode] Incompatible grant types"); } - + // make sure we've got the right authentication method if (client.getTokenEndpointAuthMethod() == null || !client.getTokenEndpointAuthMethod().equals(AuthMethod.PRIVATE_KEY)) { throw new IllegalArgumentException("[HEART mode] Client credentials clients must use the private_key authentication method"); } - + // make sure we've got a redirect URI if (!client.getRedirectUris().isEmpty()) { throw new IllegalArgumentException("[HEART mode] Client credentials clients must not register a redirect URI"); } } - + if (client.getGrantTypes().contains("password")) { throw new IllegalArgumentException("[HEART mode] Password grant type is forbidden"); } @@ -309,14 +309,14 @@ private void checkHeartMode(ClientDetailsEntity client) { customScheme = true; } } - + // now we make sure the client has a URI in only one of each of the three categories if (!((localhost ^ remoteHttps ^ customScheme) && !(localhost && remoteHttps && customScheme))) { throw new IllegalArgumentException("[HEART mode] Can't have more than one class of redirect URI"); } } - + } } @@ -386,16 +386,16 @@ public void deleteClient(ClientDetailsEntity client) throws InvalidClientExcepti /** * Update the oldClient with information from the newClient. The * id from oldClient is retained. - * + * * Checks to make sure the refresh grant type and * the scopes are set appropriately. - * + * * Checks to make sure the redirect URIs aren't blacklisted. - * + * * Attempts to load the redirect URI (possibly cached) to check the * sector identifier against the contents there. - * - * + * + * */ @Override public ClientDetailsEntity updateClient(ClientDetailsEntity oldClient, ClientDetailsEntity newClient) throws IllegalArgumentException { @@ -412,7 +412,7 @@ public ClientDetailsEntity updateClient(ClientDetailsEntity oldClient, ClientDet // make sure we don't have both a JWKS and a JWKS URI ensureKeyConsistency(newClient); - + // check consistency when using HEART mode checkHeartMode(newClient); @@ -460,7 +460,7 @@ public ClientDetailsEntity generateClientSecret(ClientDetailsEntity client) { /** * Utility class to load a sector identifier's set of authorized redirect URIs. - * + * * @author jricher * */ diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java index ad0a664919..6b9d2d9aff 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.service.impl; @@ -71,7 +71,7 @@ /** * @author jricher - * + * */ @Service("defaultOAuth2ProviderTokenService") public class DefaultOAuth2ProviderTokenService implements OAuth2TokenEntityService { @@ -157,7 +157,7 @@ private OAuth2AccessTokenEntity clearExpiredAccessToken(OAuth2AccessTokenEntity return token; } } - + /** * Utility function to delete a refresh token that's expired before returning it. * @param token the token to check @@ -175,7 +175,7 @@ private OAuth2RefreshTokenEntity clearExpiredRefreshToken(OAuth2RefreshTokenEnti return token; } } - + @Override public OAuth2AccessTokenEntity createAccessToken(OAuth2Authentication authentication) throws AuthenticationException, InvalidClientException { if (authentication != null && authentication.getOAuth2Request() != null) { @@ -188,14 +188,14 @@ public OAuth2AccessTokenEntity createAccessToken(OAuth2Authentication authentica throw new InvalidClientException("Client not found: " + request.getClientId()); } - + // handle the PKCE code challenge if present if (request.getExtensions().containsKey(CODE_CHALLENGE)) { String challenge = (String) request.getExtensions().get(CODE_CHALLENGE); PKCEAlgorithm alg = PKCEAlgorithm.parse((String) request.getExtensions().get(CODE_CHALLENGE_METHOD)); - + String verifier = request.getRequestParameters().get(CODE_VERIFIER); - + if (alg.equals(PKCEAlgorithm.plain)) { // do a direct string comparison if (!challenge.equals(verifier)) { @@ -213,10 +213,10 @@ public OAuth2AccessTokenEntity createAccessToken(OAuth2Authentication authentica logger.error("Unknown algorithm for PKCE digest", e); } } - + } - + OAuth2AccessTokenEntity token = new OAuth2AccessTokenEntity();//accessTokenFactory.createNewAccessToken(); // attach the client @@ -492,41 +492,41 @@ public List getRefreshTokensForClient(ClientDetailsEnt public void clearExpiredTokens() { logger.debug("Cleaning out all expired tokens"); - new AbstractPageOperationTemplate("clearExpiredAccessTokens") { - @Override - public Collection fetchPage() { - return tokenRepository.getAllExpiredAccessTokens(new DefaultPageCriteria()); - } - - @Override - public void doOperation(OAuth2AccessTokenEntity item) { - revokeAccessToken(item); - } - }.execute(); - - new AbstractPageOperationTemplate("clearExpiredRefreshTokens") { - @Override - public Collection fetchPage() { - return tokenRepository.getAllExpiredRefreshTokens(new DefaultPageCriteria()); - } - - @Override - public void doOperation(OAuth2RefreshTokenEntity item) { - revokeRefreshToken(item); - } - }.execute(); - - new AbstractPageOperationTemplate("clearExpiredAuthenticationHolders") { - @Override - public Collection fetchPage() { - return authenticationHolderRepository.getOrphanedAuthenticationHolders(new DefaultPageCriteria()); - } - - @Override - public void doOperation(AuthenticationHolderEntity item) { - authenticationHolderRepository.remove(item); - } - }.execute(); + new AbstractPageOperationTemplate("clearExpiredAccessTokens") { + @Override + public Collection fetchPage() { + return tokenRepository.getAllExpiredAccessTokens(new DefaultPageCriteria()); + } + + @Override + public void doOperation(OAuth2AccessTokenEntity item) { + revokeAccessToken(item); + } + }.execute(); + + new AbstractPageOperationTemplate("clearExpiredRefreshTokens") { + @Override + public Collection fetchPage() { + return tokenRepository.getAllExpiredRefreshTokens(new DefaultPageCriteria()); + } + + @Override + public void doOperation(OAuth2RefreshTokenEntity item) { + revokeRefreshToken(item); + } + }.execute(); + + new AbstractPageOperationTemplate("clearExpiredAuthenticationHolders") { + @Override + public Collection fetchPage() { + return authenticationHolderRepository.getOrphanedAuthenticationHolders(new DefaultPageCriteria()); + } + + @Override + public void doOperation(AuthenticationHolderEntity item) { + authenticationHolderRepository.remove(item); + } + }.execute(); } /* (non-Javadoc) @@ -535,12 +535,12 @@ public void doOperation(AuthenticationHolderEntity item) { @Override public OAuth2AccessTokenEntity saveAccessToken(OAuth2AccessTokenEntity accessToken) { OAuth2AccessTokenEntity newToken = tokenRepository.saveAccessToken(accessToken); - + // if the old token has any additional information for the return from the token endpoint, carry it through here after save if (accessToken.getAdditionalInformation() != null && !accessToken.getAdditionalInformation().isEmpty()) { newToken.getAdditionalInformation().putAll(accessToken.getAdditionalInformation()); } - + return newToken; } diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultSystemScopeService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultSystemScopeService.java index 7f96c1de9b..0c9debcbb9 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultSystemScopeService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultSystemScopeService.java @@ -15,12 +15,11 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.service.impl; import java.util.LinkedHashSet; -import java.util.List; import java.util.Set; import org.mitre.oauth2.model.SystemScope; @@ -30,13 +29,10 @@ import org.springframework.stereotype.Service; import com.google.common.base.Function; -import com.google.common.base.Joiner; import com.google.common.base.Predicate; import com.google.common.base.Predicates; -import com.google.common.base.Splitter; import com.google.common.base.Strings; import com.google.common.collect.Collections2; -import com.google.common.collect.Lists; import com.google.common.collect.Sets; /** diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/token/ChainedTokenGranter.java b/openid-connect-server/src/main/java/org/mitre/oauth2/token/ChainedTokenGranter.java index acb36a5d2c..00bf53a946 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/token/ChainedTokenGranter.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/token/ChainedTokenGranter.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.token; diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/token/DeviceTokenGranter.java b/openid-connect-server/src/main/java/org/mitre/oauth2/token/DeviceTokenGranter.java index 7a47aa19ba..c9a6c24310 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/token/DeviceTokenGranter.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/token/DeviceTokenGranter.java @@ -37,9 +37,9 @@ /** * Implements https://tools.ietf.org/html/draft-ietf-oauth-device-flow - * + * * @see DeviceEndpoint - * + * * @author jricher * */ @@ -47,7 +47,7 @@ public class DeviceTokenGranter extends AbstractTokenGranter { public static final String GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code"; - + @Autowired private DeviceCodeService deviceCodeService; @@ -68,37 +68,37 @@ protected DeviceTokenGranter(AuthorizationServerTokenServices tokenServices, Cli protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) { String deviceCode = tokenRequest.getRequestParameters().get("device_code"); - + // look up the device code and consume it DeviceCode dc = deviceCodeService.consumeDeviceCode(deviceCode, client); - + if (dc != null) { - + // make sure the code hasn't expired yet if (dc.getExpiration() != null && dc.getExpiration().before(new Date())) { // TODO: return an error throw new DeviceCodeExpiredException("Device code has expired " + deviceCode); - + } else if (!dc.isApproved()) { - + // still waiting for approval throw new AuthorizationPendingException("Authorization pending for code " + deviceCode); - + } else { // inherit the (approved) scopes from the original request tokenRequest.setScope(dc.getScope()); - + OAuth2Authentication auth = new OAuth2Authentication(getRequestFactory().createOAuth2Request(client, tokenRequest), dc.getAuthenticationHolder().getUserAuth()); - + return auth; } } else { throw new InvalidGrantException("Invalid device code: " + deviceCode); } - + } - - - + + + } diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/token/JWTAssertionTokenGranter.java b/openid-connect-server/src/main/java/org/mitre/oauth2/token/JWTAssertionTokenGranter.java index fd0383df20..bcbcc4c450 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/token/JWTAssertionTokenGranter.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/token/JWTAssertionTokenGranter.java @@ -15,19 +15,17 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.token; import java.text.ParseException; import org.mitre.jwt.assertion.AssertionValidator; -import org.mitre.jwt.signer.service.JWTSigningAndValidationService; import org.mitre.oauth2.assertion.AssertionOAuth2RequestFactory; import org.mitre.oauth2.service.ClientDetailsEntityService; import org.mitre.oauth2.service.OAuth2TokenEntityService; import org.mitre.openid.connect.assertion.JWTBearerAssertionAuthenticationToken; -import org.mitre.openid.connect.config.ConfigurationPropertiesBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.security.core.AuthenticationException; @@ -51,26 +49,16 @@ public class JWTAssertionTokenGranter extends AbstractTokenGranter { private static final String grantType = "urn:ietf:params:oauth:grant-type:jwt-bearer"; - // keep down-cast versions so we can get to the right queries - private OAuth2TokenEntityService tokenServices; - - @Autowired - private JWTSigningAndValidationService jwtService; - - @Autowired - private ConfigurationPropertiesBean config; - @Autowired @Qualifier("jwtAssertionValidator") private AssertionValidator validator; - + @Autowired private AssertionOAuth2RequestFactory assertionFactory; @Autowired public JWTAssertionTokenGranter(OAuth2TokenEntityService tokenServices, ClientDetailsEntityService clientDetailsService, OAuth2RequestFactory requestFactory) { super(tokenServices, clientDetailsService, requestFactory, grantType); - this.tokenServices = tokenServices; } /* (non-Javadoc) @@ -82,23 +70,23 @@ protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, Tok try { String incomingAssertionValue = tokenRequest.getRequestParameters().get("assertion"); JWT assertion = JWTParser.parse(incomingAssertionValue); - + if (validator.isValid(assertion)) { - + // our validator says it's OK, time to make a token from it // the real work happens in the assertion factory and the token services return new OAuth2Authentication(assertionFactory.createOAuth2Request(client, tokenRequest, assertion), new JWTBearerAssertionAuthenticationToken(assertion, client.getAuthorities())); - + } else { logger.warn("Incoming assertion did not pass validator, rejecting"); return null; } - + } catch (ParseException e) { logger.warn("Unable to parse incoming assertion"); } - + // if we had made a token, we'd have returned it by now, so return null here to close out with no created token return null; diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/token/ScopeServiceAwareOAuth2RequestValidator.java b/openid-connect-server/src/main/java/org/mitre/oauth2/token/ScopeServiceAwareOAuth2RequestValidator.java index a0b3581e11..f6cb91da4c 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/token/ScopeServiceAwareOAuth2RequestValidator.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/token/ScopeServiceAwareOAuth2RequestValidator.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.token; @@ -30,12 +30,12 @@ import org.springframework.security.oauth2.provider.TokenRequest; /** - * + * * Validates the scopes on a request by comparing them against a client's * allowed scopes, but allow custom scopes to function through the system scopes - * + * * @author jricher - * + * */ public class ScopeServiceAwareOAuth2RequestValidator implements OAuth2RequestValidator { diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/view/TokenApiView.java b/openid-connect-server/src/main/java/org/mitre/oauth2/view/TokenApiView.java index b37aebc108..d668605e6f 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/view/TokenApiView.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/view/TokenApiView.java @@ -56,71 +56,71 @@ public class TokenApiView extends AbstractView { private static final Logger logger = LoggerFactory.getLogger(TokenApiView.class); private Gson gson = new GsonBuilder() - .setExclusionStrategies(new ExclusionStrategy() { + .setExclusionStrategies(new ExclusionStrategy() { - @Override - public boolean shouldSkipField(FieldAttributes f) { - return false; - } + @Override + public boolean shouldSkipField(FieldAttributes f) { + return false; + } - @Override - public boolean shouldSkipClass(Class clazz) { - // skip the JPA binding wrapper - if (clazz.equals(BeanPropertyBindingResult.class)) { - return true; - } - return false; - } + @Override + public boolean shouldSkipClass(Class clazz) { + // skip the JPA binding wrapper + if (clazz.equals(BeanPropertyBindingResult.class)) { + return true; + } + return false; + } - }) - .registerTypeAdapter(OAuth2AccessTokenEntity.class, new JsonSerializer() { + }) + .registerTypeAdapter(OAuth2AccessTokenEntity.class, new JsonSerializer() { - @Override - public JsonElement serialize(OAuth2AccessTokenEntity src, - Type typeOfSrc, JsonSerializationContext context) { + @Override + public JsonElement serialize(OAuth2AccessTokenEntity src, + Type typeOfSrc, JsonSerializationContext context) { - JsonObject o = new JsonObject(); + JsonObject o = new JsonObject(); - o.addProperty("value", src.getValue()); - o.addProperty("id", src.getId()); - o.addProperty("refreshTokenId", src.getRefreshToken() != null ? src.getRefreshToken().getId() : null); + o.addProperty("value", src.getValue()); + o.addProperty("id", src.getId()); + o.addProperty("refreshTokenId", src.getRefreshToken() != null ? src.getRefreshToken().getId() : null); - o.add("scopes", context.serialize(src.getScope())); + o.add("scopes", context.serialize(src.getScope())); - o.addProperty("clientId", src.getClient().getClientId()); - o.addProperty("userId", src.getAuthenticationHolder().getAuthentication().getName()); + o.addProperty("clientId", src.getClient().getClientId()); + o.addProperty("userId", src.getAuthenticationHolder().getAuthentication().getName()); - o.add("expiration", context.serialize(src.getExpiration())); + o.add("expiration", context.serialize(src.getExpiration())); - return o; - } + return o; + } - }) - .registerTypeAdapter(OAuth2RefreshTokenEntity.class, new JsonSerializer() { + }) + .registerTypeAdapter(OAuth2RefreshTokenEntity.class, new JsonSerializer() { - @Override - public JsonElement serialize(OAuth2RefreshTokenEntity src, - Type typeOfSrc, JsonSerializationContext context) { - JsonObject o = new JsonObject(); + @Override + public JsonElement serialize(OAuth2RefreshTokenEntity src, + Type typeOfSrc, JsonSerializationContext context) { + JsonObject o = new JsonObject(); - o.addProperty("value", src.getValue()); - o.addProperty("id", src.getId()); + o.addProperty("value", src.getValue()); + o.addProperty("id", src.getId()); - o.add("scopes", context.serialize(src.getAuthenticationHolder().getAuthentication().getOAuth2Request().getScope())); + o.add("scopes", context.serialize(src.getAuthenticationHolder().getAuthentication().getOAuth2Request().getScope())); - o.addProperty("clientId", src.getClient().getClientId()); - o.addProperty("userId", src.getAuthenticationHolder().getAuthentication().getName()); + o.addProperty("clientId", src.getClient().getClientId()); + o.addProperty("userId", src.getAuthenticationHolder().getAuthentication().getName()); - o.add("expiration", context.serialize(src.getExpiration())); + o.add("expiration", context.serialize(src.getExpiration())); - return o; - } + return o; + } - }) - .serializeNulls() - .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") - .create(); + }) + .serializeNulls() + .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") + .create(); @Override protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) { diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/AuthenticationUtilities.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/AuthenticationUtilities.java index 281e5661fb..2d148fda9b 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/AuthenticationUtilities.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/AuthenticationUtilities.java @@ -25,9 +25,9 @@ import com.google.common.collect.ImmutableSet; /** - * + * * Utility class to enforce OAuth scopes in authenticated requests. - * + * * @author jricher * */ diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/CorsFilter.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/CorsFilter.java index b9e7d5fa0e..c4fd9124ae 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/CorsFilter.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/CorsFilter.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.web; @@ -30,11 +30,11 @@ import org.springframework.web.filter.OncePerRequestFilter; /** - * + * * Implements Cross-Origin Resource Sharing (CORS) headers. This filter adds the CORS * headers to all requests that pass through it, and as such it should be used only * on endpoints that require CORS support. - * + * * @author jricher * */ diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java index a14f7dcb0b..f141e8cce5 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java @@ -46,7 +46,6 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.exceptions.InvalidClientException; -import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.common.util.RandomValueStringGenerator; import org.springframework.security.oauth2.provider.AuthorizationRequest; @@ -59,7 +58,6 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.Sets; /** @@ -75,41 +73,41 @@ public class DeviceEndpoint { public static final String URL = "devicecode"; public static final String USER_URL = "device"; - + public static final Logger logger = LoggerFactory.getLogger(DeviceEndpoint.class); - + @Autowired private ClientDetailsEntityService clientService; - + @Autowired private SystemScopeService scopeService; - + @Autowired private ConfigurationPropertiesBean config; - + @Autowired private DeviceCodeService deviceCodeService; - + @Autowired private OAuth2RequestFactory oAuth2RequestFactory; - + private RandomValueStringGenerator randomGenerator = new RandomValueStringGenerator(); - + @RequestMapping(value = "/" + URL, method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public String requestDeviceCode(@RequestParam("client_id") String clientId, @RequestParam(name="scope", required=false) String scope, Map parameters, ModelMap model) { - + ClientDetailsEntity client; try { client = clientService.loadClientByClientId(clientId); - + // make sure this client can do the device flow - + Collection authorizedGrantTypes = client.getAuthorizedGrantTypes(); if (authorizedGrantTypes != null && !authorizedGrantTypes.isEmpty() && !authorizedGrantTypes.contains(DeviceTokenGranter.GRANT_TYPE)) { throw new InvalidClientException("Unauthorized grant type: " + DeviceTokenGranter.GRANT_TYPE); } - + } catch (IllegalArgumentException e) { logger.error("IllegalArgumentException was thrown when attempting to load client", e); model.put(HttpCodeView.CODE, HttpStatus.BAD_REQUEST); @@ -125,7 +123,7 @@ public String requestDeviceCode(@RequestParam("client_id") String clientId, @Req // make sure the client is allowed to ask for those scopes Set requestedScopes = OAuth2Utils.parseParameterList(scope); Set allowedScopes = client.getScope(); - + if (!scopeService.scopesMatch(allowedScopes, requestedScopes)) { // client asked for scopes it can't have logger.error("Client asked for " + requestedScopes + " but is allowed " + allowedScopes); @@ -133,17 +131,17 @@ public String requestDeviceCode(@RequestParam("client_id") String clientId, @Req model.put(JsonErrorView.ERROR, "invalid_scope"); return JsonErrorView.VIEWNAME; } - + // if we got here the request is legit - + // create a device code, should be big and random String deviceCode = UUID.randomUUID().toString(); - + // create a user code, should be random but small and typable String userCode = randomGenerator.generate(); - DeviceCode dc = deviceCodeService.createNewDeviceCode(deviceCode, userCode, requestedScopes, client, parameters); - + deviceCodeService.createNewDeviceCode(deviceCode, userCode, requestedScopes, client, parameters); + Map response = new HashMap<>(); response.put("device_code", deviceCode); response.put("user_code", userCode); @@ -151,37 +149,37 @@ public String requestDeviceCode(@RequestParam("client_id") String clientId, @Req if (client.getDeviceCodeValiditySeconds() != null) { response.put("expires_in", client.getDeviceCodeValiditySeconds()); } - + model.put(JsonEntityView.ENTITY, response); - + return JsonEntityView.VIEWNAME; - + } @PreAuthorize("hasRole('ROLE_USER')") @RequestMapping(value = "/" + USER_URL, method = RequestMethod.GET) public String requestUserCode(ModelMap model) { - + // print out a page that asks the user to enter their user code // user must be logged in - + return "requestUserCode"; } - + @PreAuthorize("hasRole('ROLE_USER')") @RequestMapping(value = "/" + USER_URL + "/verify", method = RequestMethod.POST) public String readUserCode(@RequestParam("user_code") String userCode, ModelMap model, HttpSession session) { // look up the request based on the user code DeviceCode dc = deviceCodeService.lookUpByUserCode(userCode); - + // we couldn't find the device code if (dc == null) { model.addAttribute("error", "noUserCode"); return "requestUserCode"; } - + // make sure the code hasn't expired yet if (dc.getExpiration() != null && dc.getExpiration().before(new Date())) { model.addAttribute("error", "expiredUserCode"); @@ -193,12 +191,12 @@ public String readUserCode(@RequestParam("user_code") String userCode, ModelMap model.addAttribute("error", "userCodeAlreadyApproved"); return "requestUserCode"; } - + ClientDetailsEntity client = clientService.loadClientByClientId(dc.getClientId()); - + model.put("client", client); model.put("dc", dc); - + // pre-process the scopes Set scopes = scopeService.fromStrings(dc.getScope()); @@ -221,17 +219,17 @@ public String readUserCode(@RequestParam("user_code") String userCode, ModelMap session.setAttribute("authorizationRequest", authorizationRequest); session.setAttribute("deviceCode", dc); - + return "approveDevice"; } - + @PreAuthorize("hasRole('ROLE_USER')") @RequestMapping(value = "/" + USER_URL + "/approve", method = RequestMethod.POST) public String approveDevice(@RequestParam("user_code") String userCode, @RequestParam(value = "user_oauth_approval") Boolean approve, ModelMap model, Authentication auth, HttpSession session) { - + AuthorizationRequest authorizationRequest = (AuthorizationRequest) session.getAttribute("authorizationRequest"); DeviceCode dc = (DeviceCode) session.getAttribute("deviceCode"); - + // make sure the form that was submitted is the one that we were expecting if (!dc.getUserCode().equals(userCode)) { model.addAttribute("error", "userCodeMismatch"); @@ -243,11 +241,11 @@ public String approveDevice(@RequestParam("user_code") String userCode, @Request model.addAttribute("error", "expiredUserCode"); return "requestUserCode"; } - + ClientDetailsEntity client = clientService.loadClientByClientId(dc.getClientId()); - + model.put("client", client); - + // user did not approve if (!approve) { model.addAttribute("approved", false); @@ -278,7 +276,7 @@ public String approveDevice(@RequestParam("user_code") String userCode, @Request model.put("scopes", sortedScopes); model.put("approved", true); - + return "deviceApproved"; } } diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/IntrospectionEndpoint.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/IntrospectionEndpoint.java index 1bcc736c2b..51832ec370 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/IntrospectionEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/IntrospectionEndpoint.java @@ -16,6 +16,8 @@ *******************************************************************************/ package org.mitre.oauth2.web; +import static org.mitre.oauth2.web.AuthenticationUtilities.ensureOAuthScope; + import java.util.Collection; import java.util.HashSet; import java.util.Map; @@ -49,13 +51,11 @@ import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; -import static org.mitre.oauth2.web.AuthenticationUtilities.ensureOAuthScope; - @Controller public class IntrospectionEndpoint { /** - * + * */ public static final String URL = "introspect"; diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuth2ExceptionHandler.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuth2ExceptionHandler.java index 74cdfdaaae..7bbf2a544d 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuth2ExceptionHandler.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuth2ExceptionHandler.java @@ -28,7 +28,7 @@ /** * Controller helper that handles OAuth2 exceptions and propagates them as JSON errors. - * + * * @author jricher * */ diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java index 39d356c85d..117d7f49a2 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java @@ -15,10 +15,13 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.web; +import static org.mitre.openid.connect.request.ConnectRequestParameters.PROMPT; +import static org.mitre.openid.connect.request.ConnectRequestParameters.PROMPT_SEPARATOR; + import java.net.URISyntaxException; import java.security.Principal; import java.util.Date; @@ -57,9 +60,6 @@ import com.google.common.collect.Sets; import com.google.gson.JsonObject; -import static org.mitre.openid.connect.request.ConnectRequestParameters.PROMPT; -import static org.mitre.openid.connect.request.ConnectRequestParameters.PROMPT_SEPARATOR; - /** * @author jricher * diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/RevocationEndpoint.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/RevocationEndpoint.java index 7c9dab0918..3b1c6b79cc 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/RevocationEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/RevocationEndpoint.java @@ -18,8 +18,6 @@ import static org.mitre.oauth2.web.AuthenticationUtilities.ensureOAuthScope; -import java.util.Collection; - import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.model.OAuth2AccessTokenEntity; import org.mitre.oauth2.model.OAuth2RefreshTokenEntity; @@ -27,7 +25,6 @@ import org.mitre.oauth2.service.OAuth2TokenEntityService; import org.mitre.oauth2.service.SystemScopeService; import org.mitre.openid.connect.view.HttpCodeView; -import org.mitre.uma.model.ResourceSet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -36,7 +33,6 @@ import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @@ -94,18 +90,18 @@ public String revoke(@RequestParam("token") String tokenValue, @RequestParam(val // client acting on its own, make sure it owns the token if (!accessToken.getClient().getClientId().equals(authClient.getClientId())) { // trying to revoke a token we don't own, throw a 403 - + logger.info("Client " + authClient.getClientId() + " tried to revoke a token owned by " + accessToken.getClient().getClientId()); - + model.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN); return HttpCodeView.VIEWNAME; } // if we got this far, we're allowed to do this tokenServices.revokeAccessToken(accessToken); - + logger.debug("Client " + authClient.getClientId() + " revoked access token " + tokenValue); - + model.addAttribute(HttpCodeView.CODE, HttpStatus.OK); return HttpCodeView.VIEWNAME; @@ -118,18 +114,18 @@ public String revoke(@RequestParam("token") String tokenValue, @RequestParam(val // client acting on its own, make sure it owns the token if (!refreshToken.getClient().getClientId().equals(authClient.getClientId())) { // trying to revoke a token we don't own, throw a 403 - + logger.info("Client " + authClient.getClientId() + " tried to revoke a token owned by " + refreshToken.getClient().getClientId()); - + model.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN); return HttpCodeView.VIEWNAME; } // if we got this far, we're allowed to do this tokenServices.revokeRefreshToken(refreshToken); - + logger.debug("Client " + authClient.getClientId() + " revoked access token " + tokenValue); - + model.addAttribute(HttpCodeView.CODE, HttpStatus.OK); return HttpCodeView.VIEWNAME; @@ -138,7 +134,7 @@ public String revoke(@RequestParam("token") String tokenValue, @RequestParam(val // neither token type was found, simply say "OK" and be on our way. logger.debug("Failed to revoke token " + tokenValue); - + model.addAttribute(HttpCodeView.CODE, HttpStatus.OK); return HttpCodeView.VIEWNAME; } diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/ScopeAPI.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/ScopeAPI.java index 6cb6f4f411..9b33e4ae85 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/ScopeAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/ScopeAPI.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.oauth2.web; diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAssertionAuthenticationToken.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAssertionAuthenticationToken.java index c544c7eb7d..6022cabaa5 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAssertionAuthenticationToken.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAssertionAuthenticationToken.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.assertion; @@ -34,7 +34,7 @@ public class JWTBearerAssertionAuthenticationToken extends AbstractAuthenticationToken { /** - * + * */ private static final long serialVersionUID = -3138213539914074617L; private String subject; diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAuthenticationProvider.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAuthenticationProvider.java index c1584d1790..c9c394dd7b 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAuthenticationProvider.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerAuthenticationProvider.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.assertion; @@ -118,17 +118,17 @@ public Authentication authenticate(Authentication authentication) throws Authent || alg.equals(JWSAlgorithm.ES512) || alg.equals(JWSAlgorithm.PS256) || alg.equals(JWSAlgorithm.PS384) - || alg.equals(JWSAlgorithm.PS512))) - || (client.getTokenEndpointAuthMethod().equals(AuthMethod.SECRET_JWT) && - (alg.equals(JWSAlgorithm.HS256) - || alg.equals(JWSAlgorithm.HS384) - || alg.equals(JWSAlgorithm.HS512)))) { + || alg.equals(JWSAlgorithm.PS512))) + || (client.getTokenEndpointAuthMethod().equals(AuthMethod.SECRET_JWT) && + (alg.equals(JWSAlgorithm.HS256) + || alg.equals(JWSAlgorithm.HS384) + || alg.equals(JWSAlgorithm.HS512)))) { // double-check the method is asymmetrical if we're in HEART mode if (config.isHeartMode() && !client.getTokenEndpointAuthMethod().equals(AuthMethod.PRIVATE_KEY)) { throw new AuthenticationServiceException("[HEART mode] Invalid authentication method"); } - + JWTSigningAndValidationService validator = validators.getValidator(client, alg); if (validator == null) { diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerClientAssertionTokenEndpointFilter.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerClientAssertionTokenEndpointFilter.java index 24f7b309fe..cfd69ade1b 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerClientAssertionTokenEndpointFilter.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JWTBearerClientAssertionTokenEndpointFilter.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.assertion; @@ -44,7 +44,7 @@ /** * Filter to check client authentication via JWT Bearer assertions. - * + * * @author jricher * */ diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/config/JsonMessageSource.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/config/JsonMessageSource.java index 49bf99855f..37744b985d 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/config/JsonMessageSource.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/config/JsonMessageSource.java @@ -54,10 +54,10 @@ public class JsonMessageSource extends AbstractMessageSource { private Locale fallbackLocale = new Locale("en"); // US English is the fallback language private Map> languageMaps = new HashMap<>(); - + @Autowired private ConfigurationPropertiesBean config; - + @Override protected MessageFormat resolveCode(String code, Locale locale) { @@ -78,7 +78,7 @@ protected MessageFormat resolveCode(String code, Locale locale) { // otherwise format the message return new MessageFormat(value, locale); } - + } /** @@ -92,7 +92,7 @@ private String getValue(String code, List langs) { // no language maps, nothing to look up return null; } - + for (JsonObject lang : langs) { String value = getValue(code, lang); if (value != null) { @@ -100,11 +100,11 @@ private String getValue(String code, List langs) { return value; } } - + // if we didn't find anything return null return null; } - + /** * Get a value from a single map * @param code @@ -165,21 +165,21 @@ private List getLanguageMap(Locale locale) { for (String namespace : config.getLanguageNamespaces()) { // full locale string, e.g. "en_US" String filename = locale.getLanguage() + "_" + locale.getCountry() + File.separator + namespace + ".json"; - + Resource r = getBaseDirectory().createRelative(filename); - + if (!r.exists()) { // fallback to language only logger.debug("Fallback locale to language only."); filename = locale.getLanguage() + File.separator + namespace + ".json"; r = getBaseDirectory().createRelative(filename); } - + logger.info("No locale loaded, trying to load from " + r); - + JsonParser parser = new JsonParser(); JsonObject obj = (JsonObject) parser.parse(new InputStreamReader(r.getInputStream(), "UTF-8")); - + set.add(obj); } languageMaps.put(locale, set); diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/AuthorizationRequestFilter.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/AuthorizationRequestFilter.java index 46f00e43f2..84f7735bb4 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/AuthorizationRequestFilter.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/AuthorizationRequestFilter.java @@ -15,11 +15,19 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.filter; -import static org.mitre.openid.connect.request.ConnectRequestParameters.*; +import static org.mitre.openid.connect.request.ConnectRequestParameters.ERROR; +import static org.mitre.openid.connect.request.ConnectRequestParameters.LOGIN_HINT; +import static org.mitre.openid.connect.request.ConnectRequestParameters.LOGIN_REQUIRED; +import static org.mitre.openid.connect.request.ConnectRequestParameters.MAX_AGE; +import static org.mitre.openid.connect.request.ConnectRequestParameters.PROMPT; +import static org.mitre.openid.connect.request.ConnectRequestParameters.PROMPT_LOGIN; +import static org.mitre.openid.connect.request.ConnectRequestParameters.PROMPT_NONE; +import static org.mitre.openid.connect.request.ConnectRequestParameters.PROMPT_SEPARATOR; +import static org.mitre.openid.connect.request.ConnectRequestParameters.STATE; import java.io.IOException; import java.net.URISyntaxException; @@ -85,11 +93,11 @@ public class AuthorizationRequestFilter extends GenericFilterBean { @Autowired(required = false) private LoginHintExtracter loginHintExtracter = new RemoveLoginHintsWithHTTP(); - + private RequestMatcher requestMatcher = new AntPathRequestMatcher("/authorize"); /** - * + * */ @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/MultiUrlRequestMatcher.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/MultiUrlRequestMatcher.java index c15fdd606a..70dda4fd4c 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/MultiUrlRequestMatcher.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/filter/MultiUrlRequestMatcher.java @@ -27,8 +27,6 @@ import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.util.Assert; -import com.google.common.collect.ImmutableSet; - /** * @author jricher * @@ -43,7 +41,7 @@ public MultiUrlRequestMatcher(Set filterProcessesUrls) { Assert.isTrue(UrlUtils.isValidRedirectUrl(filterProcessesUrl), filterProcessesUrl + " isn't a valid URL"); matchers.add(new AntPathRequestMatcher(filterProcessesUrl)); } - + } @Override @@ -53,7 +51,7 @@ public boolean matches(HttpServletRequest request) { return true; } } - + return false; } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaAddressRepository.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaAddressRepository.java index bd0dc5a25c..51f3adcb7f 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaAddressRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaAddressRepository.java @@ -26,9 +26,9 @@ /** * JPA Address repository implementation - * + * * @author Michael Joseph Walsh - * + * */ @Repository public class JpaAddressRepository implements AddressRepository { diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaApprovedSiteRepository.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaApprovedSiteRepository.java index d7ea0b59a4..55372c6987 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaApprovedSiteRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaApprovedSiteRepository.java @@ -16,6 +16,8 @@ *******************************************************************************/ package org.mitre.openid.connect.repository.impl; +import static org.mitre.util.jpa.JpaUtil.saveOrUpdate; + import java.util.Collection; import javax.persistence.EntityManager; @@ -27,11 +29,9 @@ import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; -import static org.mitre.util.jpa.JpaUtil.saveOrUpdate; - /** * JPA ApprovedSite repository implementation - * + * * @author Michael Joseph Walsh, aanganes * */ diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaBlacklistedSiteRepository.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaBlacklistedSiteRepository.java index b8a6b08cf9..67c1eb9205 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaBlacklistedSiteRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaBlacklistedSiteRepository.java @@ -15,10 +15,12 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.repository.impl; +import static org.mitre.util.jpa.JpaUtil.saveOrUpdate; + import java.util.Collection; import javax.persistence.EntityManager; @@ -30,8 +32,6 @@ import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; -import static org.mitre.util.jpa.JpaUtil.saveOrUpdate; - /** * @author jricher * diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaPairwiseIdentifierRepository.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaPairwiseIdentifierRepository.java index 465050ae58..b8be0b66d6 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaPairwiseIdentifierRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaPairwiseIdentifierRepository.java @@ -15,10 +15,13 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.repository.impl; +import static org.mitre.util.jpa.JpaUtil.getSingleResult; +import static org.mitre.util.jpa.JpaUtil.saveOrUpdate; + import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.TypedQuery; @@ -28,9 +31,6 @@ import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; -import static org.mitre.util.jpa.JpaUtil.getSingleResult; -import static org.mitre.util.jpa.JpaUtil.saveOrUpdate; - /** * @author jricher * diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaUserInfoRepository.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaUserInfoRepository.java index 4db05ebfb7..eadf881780 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaUserInfoRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaUserInfoRepository.java @@ -16,6 +16,8 @@ *******************************************************************************/ package org.mitre.openid.connect.repository.impl; +import static org.mitre.util.jpa.JpaUtil.getSingleResult; + import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.TypedQuery; @@ -25,11 +27,9 @@ import org.mitre.openid.connect.repository.UserInfoRepository; import org.springframework.stereotype.Repository; -import static org.mitre.util.jpa.JpaUtil.getSingleResult; - /** * JPA UserInfo repository implementation - * + * * @author Michael Joseph Walsh * */ diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaWhitelistedSiteRepository.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaWhitelistedSiteRepository.java index 63552bde91..c571fb6b2e 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaWhitelistedSiteRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaWhitelistedSiteRepository.java @@ -16,6 +16,8 @@ *******************************************************************************/ package org.mitre.openid.connect.repository.impl; +import static org.mitre.util.jpa.JpaUtil.saveOrUpdate; + import java.util.Collection; import javax.persistence.EntityManager; @@ -28,11 +30,9 @@ import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; -import static org.mitre.util.jpa.JpaUtil.saveOrUpdate; - /** * JPA WhitelistedSite repository implementation - * + * * @author Michael Joseph Walsh, aanganes * */ diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectOAuth2RequestFactory.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectOAuth2RequestFactory.java index 644ed19e7c..a71aa6c6fc 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectOAuth2RequestFactory.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectOAuth2RequestFactory.java @@ -17,9 +17,11 @@ package org.mitre.openid.connect.request; -import static org.mitre.openid.connect.request.ConnectRequestParameters.*; +import static org.mitre.openid.connect.request.ConnectRequestParameters.AUD; import static org.mitre.openid.connect.request.ConnectRequestParameters.CLAIMS; import static org.mitre.openid.connect.request.ConnectRequestParameters.CLIENT_ID; +import static org.mitre.openid.connect.request.ConnectRequestParameters.CODE_CHALLENGE; +import static org.mitre.openid.connect.request.ConnectRequestParameters.CODE_CHALLENGE_METHOD; import static org.mitre.openid.connect.request.ConnectRequestParameters.DISPLAY; import static org.mitre.openid.connect.request.ConnectRequestParameters.LOGIN_HINT; import static org.mitre.openid.connect.request.ConnectRequestParameters.MAX_AGE; @@ -43,7 +45,6 @@ import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.model.PKCEAlgorithm; import org.mitre.oauth2.service.ClientDetailsEntityService; -import org.mitre.oauth2.service.SystemScopeService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -81,9 +82,6 @@ public class ConnectOAuth2RequestFactory extends DefaultOAuth2RequestFactory { @Autowired private ClientKeyCacheService validators; - @Autowired - private SystemScopeService systemScopes; - @Autowired private JWTEncryptionAndDecryptionService encryptionService; @@ -147,7 +145,7 @@ public AuthorizationRequest createAuthorizationRequest(Map input // if the client doesn't specify a code challenge transformation method, it's "plain" request.getExtensions().put(CODE_CHALLENGE_METHOD, PKCEAlgorithm.plain.getName()); } - + } if (inputParams.containsKey(REQUEST)) { @@ -179,7 +177,7 @@ public AuthorizationRequest createAuthorizationRequest(Map input * * @param jwtString * @param request - */ + */ private void processRequestObject(String jwtString, AuthorizationRequest request) { // parse the request object diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectRequestParameters.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectRequestParameters.java index 584d09a835..6db30d320a 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectRequestParameters.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/request/ConnectRequestParameters.java @@ -43,13 +43,13 @@ public interface ConnectRequestParameters { // responses public String ERROR = "error"; public String LOGIN_REQUIRED = "login_required"; - + // audience public String AUD = "aud"; - + // PKCE public String CODE_CHALLENGE = "code_challenge"; public String CODE_CHALLENGE_METHOD = "code_challenge_method"; public String CODE_VERIFIER = "code_verifier"; - + } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultApprovedSiteService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultApprovedSiteService.java index b2bf23e1d7..e4db529d40 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultApprovedSiteService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultApprovedSiteService.java @@ -39,7 +39,7 @@ /** * Implementation of the ApprovedSiteService - * + * * @author Michael Joseph Walsh, aanganes * */ @@ -184,8 +184,8 @@ private Collection getExpired() { @Override public List getApprovedAccessTokens( ApprovedSite approvedSite) { - return tokenRepository.getAccessTokensForApprovedSite(approvedSite); + return tokenRepository.getAccessTokensForApprovedSite(approvedSite); } - + } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultBlacklistedSiteService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultBlacklistedSiteService.java index 93816056ae..38c6754afe 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultBlacklistedSiteService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultBlacklistedSiteService.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.service.impl; diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultOIDCTokenService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultOIDCTokenService.java index c04e5af3df..15e764823f 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultOIDCTokenService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultOIDCTokenService.java @@ -64,7 +64,7 @@ import com.nimbusds.jwt.SignedJWT; /** * Default implementation of service to create specialty OpenID Connect tokens. - * + * * @author Amanda Anganes * */ @@ -271,12 +271,12 @@ private OAuth2AccessTokenEntity createAssociatedToken(ClientDetailsEntity client token.setAuthenticationHolder(authHolder); JWTClaimsSet claims = new JWTClaimsSet.Builder() - .audience(Lists.newArrayList(client.getClientId())) - .issuer(configBean.getIssuer()) - .issueTime(new Date()) - .expirationTime(token.getExpiration()) - .jwtID(UUID.randomUUID().toString()) // set a random NONCE in the middle of it - .build(); + .audience(Lists.newArrayList(client.getClientId())) + .issuer(configBean.getIssuer()) + .issueTime(new Date()) + .expirationTime(token.getExpiration()) + .jwtID(UUID.randomUUID().toString()) // set a random NONCE in the middle of it + .build(); JWSAlgorithm signingAlg = jwtService.getDefaultSigningAlgorithm(); JWSHeader header = new JWSHeader(signingAlg, null, null, null, null, null, null, null, null, null, diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultScopeClaimTranslationService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultScopeClaimTranslationService.java index 0dfeb86e3a..d0937cc017 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultScopeClaimTranslationService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultScopeClaimTranslationService.java @@ -17,19 +17,17 @@ package org.mitre.openid.connect.service.impl; import java.util.HashSet; -import java.util.Map; import java.util.Set; import org.mitre.openid.connect.service.ScopeClaimTranslationService; import org.springframework.stereotype.Service; import com.google.common.collect.HashMultimap; -import com.google.common.collect.Maps; import com.google.common.collect.SetMultimap; /** * Service to map scopes to claims, and claims to Java field names - * + * * @author Amanda Anganes * */ diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultStatsService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultStatsService.java index c22c1dd58d..d7897bec27 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultStatsService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultStatsService.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.service.impl; @@ -26,8 +26,6 @@ import java.util.Set; import java.util.concurrent.TimeUnit; -import org.mitre.oauth2.model.ClientDetailsEntity; -import org.mitre.oauth2.service.ClientDetailsEntityService; import org.mitre.openid.connect.model.ApprovedSite; import org.mitre.openid.connect.model.ClientStat; import org.mitre.openid.connect.service.ApprovedSiteService; @@ -37,8 +35,6 @@ import com.google.common.base.Supplier; import com.google.common.base.Suppliers; -import com.google.common.collect.HashMultiset; -import com.google.common.collect.Multiset; /** * @author jricher @@ -96,10 +92,10 @@ private Map computeSummaryStats() { public ClientStat getCountForClientId(String clientId) { Collection approvedSites = approvedSiteService.getByClientId(clientId); - + ClientStat stat = new ClientStat(); stat.setApprovedSiteCount(approvedSites.size()); - + return stat; } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultUserInfoService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultUserInfoService.java index 4acc77e3b9..fbcfb8cc62 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultUserInfoService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultUserInfoService.java @@ -28,9 +28,9 @@ /** * Implementation of the UserInfoService - * + * * @author Michael Joseph Walsh, jricher - * + * */ @Service public class DefaultUserInfoService implements UserInfoService { diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultWhitelistedSiteService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultWhitelistedSiteService.java index 20611c6c3f..4b9244c0bb 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultWhitelistedSiteService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultWhitelistedSiteService.java @@ -27,9 +27,9 @@ /** * Implementation of the WhitelistedSiteService - * + * * @author Michael Joseph Walsh, aanganes - * + * */ @Service @Transactional(value="defaultTransactionManager") diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DummyResourceSetService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DummyResourceSetService.java index 1b54dcab81..43aa28dc41 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DummyResourceSetService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DummyResourceSetService.java @@ -28,7 +28,7 @@ /** * Dummy resource set service that doesn't do anything; acts as a stub for the * introspection service when the UMA functionality is disabled. - * + * * @author jricher * */ diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/InMemoryClientLogoLoadingService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/InMemoryClientLogoLoadingService.java index 428c7c51f5..3bbbaa333a 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/InMemoryClientLogoLoadingService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/InMemoryClientLogoLoadingService.java @@ -23,7 +23,6 @@ import org.apache.commons.io.IOUtils; import org.apache.http.HttpEntity; -import org.apache.http.HttpException; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; @@ -31,7 +30,6 @@ import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.openid.connect.model.CachedImage; import org.mitre.openid.connect.service.ClientLogoLoadingService; -import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.stereotype.Service; import com.google.common.base.Strings; @@ -54,18 +52,18 @@ public InMemoryClientLogoLoadingService() { } /** - * + * */ public InMemoryClientLogoLoadingService(HttpClient httpClient) { - + cache = CacheBuilder.newBuilder() .maximumSize(100) .expireAfterAccess(14, TimeUnit.DAYS) .build(new ClientLogoFetcher(httpClient)); - + } - - + + /* (non-Javadoc) * @see org.mitre.openid.connect.service.ClientLogoLoadingService#getLogo(org.mitre.oauth2.model.ClientDetailsEntity) */ @@ -104,15 +102,15 @@ public ClientLogoFetcher(HttpClient httpClient) { public CachedImage load(ClientDetailsEntity key) throws Exception { try { HttpResponse response = httpClient.execute(new HttpGet(key.getLogoUri())); - + HttpEntity entity = response.getEntity(); - + CachedImage image = new CachedImage(); - + image.setContentType(entity.getContentType().getValue()); image.setLength(entity.getContentLength()); image.setData(IOUtils.toByteArray(entity.getContent())); - + return image; } catch (IOException e) { throw new IllegalArgumentException("Unable to load client image."); diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_0.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_0.java index c295836268..f1097e904f 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_0.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_0.java @@ -16,6 +16,9 @@ *******************************************************************************/ package org.mitre.openid.connect.service.impl; +import static org.mitre.util.JsonUtils.readMap; +import static org.mitre.util.JsonUtils.readSet; + import java.io.IOException; import java.text.ParseException; import java.util.Collection; @@ -68,9 +71,6 @@ import com.nimbusds.jose.JWEAlgorithm; import com.nimbusds.jose.JWSAlgorithm; import com.nimbusds.jwt.JWTParser; - -import static org.mitre.util.JsonUtils.readMap; -import static org.mitre.util.JsonUtils.readSet; /** * * Data service to import MITREid 1.0 configuration. @@ -103,10 +103,10 @@ public class MITREidDataService_1_0 extends MITREidDataServiceSupport implements @Autowired(required = false) private List extensions = Collections.emptyList(); - private MITREidDataServiceMaps maps = new MITREidDataServiceMaps(); - + private MITREidDataServiceMaps maps = new MITREidDataServiceMaps(); + private static final String THIS_VERSION = MITREID_CONNECT_1_0; - + @Override public boolean supportsVersion(String version) { return THIS_VERSION.equals(version); @@ -135,46 +135,46 @@ public void importData(JsonReader reader) throws IOException { while (reader.hasNext()) { JsonToken tok = reader.peek(); switch (tok) { - case NAME: - String name = reader.nextName(); - // find out which member it is - if (name.equals(CLIENTS)) { - readClients(reader); - } else if (name.equals(GRANTS)) { - readGrants(reader); - } else if (name.equals(WHITELISTEDSITES)) { - readWhitelistedSites(reader); - } else if (name.equals(BLACKLISTEDSITES)) { - readBlacklistedSites(reader); - } else if (name.equals(AUTHENTICATIONHOLDERS)) { - readAuthenticationHolders(reader); - } else if (name.equals(ACCESSTOKENS)) { - readAccessTokens(reader); - } else if (name.equals(REFRESHTOKENS)) { - readRefreshTokens(reader); - } else if (name.equals(SYSTEMSCOPES)) { - readSystemScopes(reader); - } else { - for (MITREidDataServiceExtension extension : extensions) { - if (extension.supportsVersion(THIS_VERSION)) { + case NAME: + String name = reader.nextName(); + // find out which member it is + if (name.equals(CLIENTS)) { + readClients(reader); + } else if (name.equals(GRANTS)) { + readGrants(reader); + } else if (name.equals(WHITELISTEDSITES)) { + readWhitelistedSites(reader); + } else if (name.equals(BLACKLISTEDSITES)) { + readBlacklistedSites(reader); + } else if (name.equals(AUTHENTICATIONHOLDERS)) { + readAuthenticationHolders(reader); + } else if (name.equals(ACCESSTOKENS)) { + readAccessTokens(reader); + } else if (name.equals(REFRESHTOKENS)) { + readRefreshTokens(reader); + } else if (name.equals(SYSTEMSCOPES)) { + readSystemScopes(reader); + } else { + for (MITREidDataServiceExtension extension : extensions) { if (extension.supportsVersion(THIS_VERSION)) { - extension.importExtensionData(name, reader); - break; + if (extension.supportsVersion(THIS_VERSION)) { + extension.importExtensionData(name, reader); + break; + } } } + // unknown token, skip it + reader.skipValue(); } - // unknown token, skip it + break; + case END_OBJECT: + // the object ended, we're done here + reader.endObject(); + continue; + default: + logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - case END_OBJECT: - // the object ended, we're done here - reader.endObject(); - continue; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; } + continue; } } fixObjectReferences(); for (MITREidDataServiceExtension extension : extensions) { @@ -203,37 +203,37 @@ private void readRefreshTokens(JsonReader reader) throws IOException { Long authHolderId = null; while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals("id")) { - currentId = reader.nextLong(); - } else if (name.equals("expiration")) { - Date date = utcToDate(reader.nextString()); - token.setExpiration(date); - } else if (name.equals("value")) { - String value = reader.nextString(); - try { - token.setJwt(JWTParser.parse(value)); - } catch (ParseException ex) { - logger.error("Unable to set refresh token value to {}", value, ex); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals("id")) { + currentId = reader.nextLong(); + } else if (name.equals("expiration")) { + Date date = utcToDate(reader.nextString()); + token.setExpiration(date); + } else if (name.equals("value")) { + String value = reader.nextString(); + try { + token.setJwt(JWTParser.parse(value)); + } catch (ParseException ex) { + logger.error("Unable to set refresh token value to {}", value, ex); + } + } else if (name.equals("clientId")) { + clientId = reader.nextString(); + } else if (name.equals("authenticationHolderId")) { + authHolderId = reader.nextLong(); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); } - } else if (name.equals("clientId")) { - clientId = reader.nextString(); - } else if (name.equals("authenticationHolderId")) { - authHolderId = reader.nextLong(); - } else { + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -265,45 +265,45 @@ private void readAccessTokens(JsonReader reader) throws IOException { Long refreshTokenId = null; while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals("id")) { - currentId = reader.nextLong(); - } else if (name.equals("expiration")) { - Date date = utcToDate(reader.nextString()); - token.setExpiration(date); - } else if (name.equals("value")) { - String value = reader.nextString(); - try { - // all tokens are JWTs - token.setJwt(JWTParser.parse(value)); - } catch (ParseException ex) { - logger.error("Unable to set refresh token value to {}", value, ex); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals("id")) { + currentId = reader.nextLong(); + } else if (name.equals("expiration")) { + Date date = utcToDate(reader.nextString()); + token.setExpiration(date); + } else if (name.equals("value")) { + String value = reader.nextString(); + try { + // all tokens are JWTs + token.setJwt(JWTParser.parse(value)); + } catch (ParseException ex) { + logger.error("Unable to set refresh token value to {}", value, ex); + } + } else if (name.equals("clientId")) { + clientId = reader.nextString(); + } else if (name.equals("authenticationHolderId")) { + authHolderId = reader.nextLong(); + } else if (name.equals("refreshTokenId")) { + refreshTokenId = reader.nextLong(); + } else if (name.equals("scope")) { + Set scope = readSet(reader); + token.setScope(scope); + } else if (name.equals("type")) { + token.setTokenType(reader.nextString()); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); } - } else if (name.equals("clientId")) { - clientId = reader.nextString(); - } else if (name.equals("authenticationHolderId")) { - authHolderId = reader.nextLong(); - } else if (name.equals("refreshTokenId")) { - refreshTokenId = reader.nextLong(); - } else if (name.equals("scope")) { - Set scope = readSet(reader); - token.setScope(scope); - } else if (name.equals("type")) { - token.setTokenType(reader.nextString()); - } else { + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -331,61 +331,61 @@ private void readAuthenticationHolders(JsonReader reader) throws IOException { Long currentId = null; while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals("id")) { - currentId = reader.nextLong(); - } else if (name.equals("ownerId")) { - //not needed - reader.skipValue(); - } else if (name.equals("authentication")) { - OAuth2Request clientAuthorization = null; - Authentication userAuthentication = null; - reader.beginObject(); - while (reader.hasNext()) { - switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String subName = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (subName.equals("clientAuthorization")) { - clientAuthorization = readAuthorizationRequest(reader); - } else if (subName.equals("userAuthentication")) { - // skip binary encoded version - reader.skipValue(); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals("id")) { + currentId = reader.nextLong(); + } else if (name.equals("ownerId")) { + //not needed + reader.skipValue(); + } else if (name.equals("authentication")) { + OAuth2Request clientAuthorization = null; + Authentication userAuthentication = null; + reader.beginObject(); + while (reader.hasNext()) { + switch (reader.peek()) { + case END_OBJECT: + continue; + case NAME: + String subName = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (subName.equals("clientAuthorization")) { + clientAuthorization = readAuthorizationRequest(reader); + } else if (subName.equals("userAuthentication")) { + // skip binary encoded version + reader.skipValue(); - } else if (subName.equals("savedUserAuthentication")) { - userAuthentication = readSavedUserAuthentication(reader); + } else if (subName.equals("savedUserAuthentication")) { + userAuthentication = readSavedUserAuthentication(reader); - } else { - logger.debug("Found unexpected entry"); - reader.skipValue(); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); + } + break; + default: + logger.debug("Found unexpected entry"); + reader.skipValue(); + continue; } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; } + reader.endObject(); + OAuth2Authentication auth = new OAuth2Authentication(clientAuthorization, userAuthentication); + ahe.setAuthentication(auth); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); } - reader.endObject(); - OAuth2Authentication auth = new OAuth2Authentication(clientAuthorization, userAuthentication); - ahe.setAuthentication(auth); - } else { + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -410,47 +410,47 @@ private OAuth2Request readAuthorizationRequest(JsonReader reader) throws IOExcep reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals("authorizationParameters")) { - authorizationParameters = readMap(reader); - } else if (name.equals("approvalParameters")) { - reader.skipValue(); - } else if (name.equals("clientId")) { - clientId = reader.nextString(); - } else if (name.equals("scope")) { - scope = readSet(reader); - } else if (name.equals("resourceIds")) { - resourceIds = readSet(reader); - } else if (name.equals("authorities")) { - Set authorityStrs = readSet(reader); - authorities = new HashSet<>(); - for (String s : authorityStrs) { - GrantedAuthority ga = new SimpleGrantedAuthority(s); - authorities.add(ga); - } - } else if (name.equals("approved")) { - approved = reader.nextBoolean(); - } else if (name.equals("denied")) { - if (approved == false) { - approved = !reader.nextBoolean(); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals("authorizationParameters")) { + authorizationParameters = readMap(reader); + } else if (name.equals("approvalParameters")) { + reader.skipValue(); + } else if (name.equals("clientId")) { + clientId = reader.nextString(); + } else if (name.equals("scope")) { + scope = readSet(reader); + } else if (name.equals("resourceIds")) { + resourceIds = readSet(reader); + } else if (name.equals("authorities")) { + Set authorityStrs = readSet(reader); + authorities = new HashSet<>(); + for (String s : authorityStrs) { + GrantedAuthority ga = new SimpleGrantedAuthority(s); + authorities.add(ga); + } + } else if (name.equals("approved")) { + approved = reader.nextBoolean(); + } else if (name.equals("denied")) { + if (approved == false) { + approved = !reader.nextBoolean(); + } + } else if (name.equals("redirectUri")) { + redirectUri = reader.nextString(); + } else if (name.equals("responseTypes")) { + responseTypes = readSet(reader); + } else { + reader.skipValue(); } - } else if (name.equals("redirectUri")) { - redirectUri = reader.nextString(); - } else if (name.equals("responseTypes")) { - responseTypes = readSet(reader); - } else { + break; + default: + logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -468,35 +468,35 @@ private SavedUserAuthentication readSavedUserAuthentication(JsonReader reader) t while (reader.hasNext()) { switch(reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals("name")) { - savedUserAuth.setName(reader.nextString()); - } else if (name.equals("sourceClass")) { - savedUserAuth.setSourceClass(reader.nextString()); - } else if (name.equals("authenticated")) { - savedUserAuth.setAuthenticated(reader.nextBoolean()); - } else if (name.equals("authorities")) { - Set authorityStrs = readSet(reader); - Set authorities = new HashSet(); - for (String s : authorityStrs) { - GrantedAuthority ga = new SimpleGrantedAuthority(s); - authorities.add(ga); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals("name")) { + savedUserAuth.setName(reader.nextString()); + } else if (name.equals("sourceClass")) { + savedUserAuth.setSourceClass(reader.nextString()); + } else if (name.equals("authenticated")) { + savedUserAuth.setAuthenticated(reader.nextBoolean()); + } else if (name.equals("authorities")) { + Set authorityStrs = readSet(reader); + Set authorities = new HashSet(); + for (String s : authorityStrs) { + GrantedAuthority ga = new SimpleGrantedAuthority(s); + authorities.add(ga); + } + savedUserAuth.setAuthorities(authorities); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); } - savedUserAuth.setAuthorities(authorities); - } else { + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } @@ -518,43 +518,43 @@ private void readGrants(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals("id")) { - currentId = reader.nextLong(); - } else if (name.equals("accessDate")) { - Date date = utcToDate(reader.nextString()); - site.setAccessDate(date); - } else if (name.equals("clientId")) { - site.setClientId(reader.nextString()); - } else if (name.equals("creationDate")) { - Date date = utcToDate(reader.nextString()); - site.setCreationDate(date); - } else if (name.equals("timeoutDate")) { - Date date = utcToDate(reader.nextString()); - site.setTimeoutDate(date); - } else if (name.equals("userId")) { - site.setUserId(reader.nextString()); - } else if (name.equals("allowedScopes")) { - Set allowedScopes = readSet(reader); - site.setAllowedScopes(allowedScopes); - } else if (name.equals("whitelistedSiteId")) { - whitelistedSiteId = reader.nextLong(); - } else if (name.equals("approvedAccessTokens")) { - tokenIds = readSet(reader); - } else { + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals("id")) { + currentId = reader.nextLong(); + } else if (name.equals("accessDate")) { + Date date = utcToDate(reader.nextString()); + site.setAccessDate(date); + } else if (name.equals("clientId")) { + site.setClientId(reader.nextString()); + } else if (name.equals("creationDate")) { + Date date = utcToDate(reader.nextString()); + site.setCreationDate(date); + } else if (name.equals("timeoutDate")) { + Date date = utcToDate(reader.nextString()); + site.setTimeoutDate(date); + } else if (name.equals("userId")) { + site.setUserId(reader.nextString()); + } else if (name.equals("allowedScopes")) { + Set allowedScopes = readSet(reader); + site.setAllowedScopes(allowedScopes); + } else if (name.equals("whitelistedSiteId")) { + whitelistedSiteId = reader.nextLong(); + } else if (name.equals("approvedAccessTokens")) { + tokenIds = readSet(reader); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); + } + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -583,28 +583,28 @@ private void readWhitelistedSites(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (name.equals("id")) { - currentId = reader.nextLong(); - } else if (name.equals("clientId")) { - wlSite.setClientId(reader.nextString()); - } else if (name.equals("creatorUserId")) { - wlSite.setCreatorUserId(reader.nextString()); - } else if (name.equals("allowedScopes")) { - Set allowedScopes = readSet(reader); - wlSite.setAllowedScopes(allowedScopes); - } else { + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (name.equals("id")) { + currentId = reader.nextLong(); + } else if (name.equals("clientId")) { + wlSite.setClientId(reader.nextString()); + } else if (name.equals("creatorUserId")) { + wlSite.setCreatorUserId(reader.nextString()); + } else if (name.equals("allowedScopes")) { + Set allowedScopes = readSet(reader); + wlSite.setAllowedScopes(allowedScopes); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); + } + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -626,23 +626,23 @@ private void readBlacklistedSites(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (name.equals("id")) { - reader.skipValue(); - } else if (name.equals("uri")) { - blSite.setUri(reader.nextString()); - } else { + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (name.equals("id")) { + reader.skipValue(); + } else if (name.equals("uri")) { + blSite.setUri(reader.nextString()); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); + } + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -663,125 +663,125 @@ private void readClients(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals("clientId")) { - client.setClientId(reader.nextString()); - } else if (name.equals("resourceIds")) { - Set resourceIds = readSet(reader); - client.setResourceIds(resourceIds); - } else if (name.equals("secret")) { - client.setClientSecret(reader.nextString()); - } else if (name.equals("scope")) { - Set scope = readSet(reader); - client.setScope(scope); - } else if (name.equals("authorities")) { - Set authorityStrs = readSet(reader); - Set authorities = new HashSet<>(); - for (String s : authorityStrs) { - GrantedAuthority ga = new SimpleGrantedAuthority(s); - authorities.add(ga); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals("clientId")) { + client.setClientId(reader.nextString()); + } else if (name.equals("resourceIds")) { + Set resourceIds = readSet(reader); + client.setResourceIds(resourceIds); + } else if (name.equals("secret")) { + client.setClientSecret(reader.nextString()); + } else if (name.equals("scope")) { + Set scope = readSet(reader); + client.setScope(scope); + } else if (name.equals("authorities")) { + Set authorityStrs = readSet(reader); + Set authorities = new HashSet<>(); + for (String s : authorityStrs) { + GrantedAuthority ga = new SimpleGrantedAuthority(s); + authorities.add(ga); + } + client.setAuthorities(authorities); + } else if (name.equals("accessTokenValiditySeconds")) { + client.setAccessTokenValiditySeconds(reader.nextInt()); + } else if (name.equals("refreshTokenValiditySeconds")) { + client.setRefreshTokenValiditySeconds(reader.nextInt()); + } else if (name.equals("redirectUris")) { + Set redirectUris = readSet(reader); + client.setRedirectUris(redirectUris); + } else if (name.equals("name")) { + client.setClientName(reader.nextString()); + } else if (name.equals("uri")) { + client.setClientUri(reader.nextString()); + } else if (name.equals("logoUri")) { + client.setLogoUri(reader.nextString()); + } else if (name.equals("contacts")) { + Set contacts = readSet(reader); + client.setContacts(contacts); + } else if (name.equals("tosUri")) { + client.setTosUri(reader.nextString()); + } else if (name.equals("tokenEndpointAuthMethod")) { + AuthMethod am = AuthMethod.getByValue(reader.nextString()); + client.setTokenEndpointAuthMethod(am); + } else if (name.equals("grantTypes")) { + Set grantTypes = readSet(reader); + client.setGrantTypes(grantTypes); + } else if (name.equals("responseTypes")) { + Set responseTypes = readSet(reader); + client.setResponseTypes(responseTypes); + } else if (name.equals("policyUri")) { + client.setPolicyUri(reader.nextString()); + } else if (name.equals("applicationType")) { + AppType appType = AppType.getByValue(reader.nextString()); + client.setApplicationType(appType); + } else if (name.equals("sectorIdentifierUri")) { + client.setSectorIdentifierUri(reader.nextString()); + } else if (name.equals("subjectType")) { + SubjectType st = SubjectType.getByValue(reader.nextString()); + client.setSubjectType(st); + } else if (name.equals("jwks_uri")) { + client.setJwksUri(reader.nextString()); + } else if (name.equals("requestObjectSigningAlg")) { + JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); + client.setRequestObjectSigningAlg(alg); + } else if (name.equals("userInfoEncryptedResponseAlg")) { + JWEAlgorithm alg = JWEAlgorithm.parse(reader.nextString()); + client.setUserInfoEncryptedResponseAlg(alg); + } else if (name.equals("userInfoEncryptedResponseEnc")) { + EncryptionMethod alg = EncryptionMethod.parse(reader.nextString()); + client.setUserInfoEncryptedResponseEnc(alg); + } else if (name.equals("userInfoSignedResponseAlg")) { + JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); + client.setUserInfoSignedResponseAlg(alg); + } else if (name.equals("idTokenSignedResonseAlg")) { + JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); + client.setIdTokenSignedResponseAlg(alg); + } else if (name.equals("idTokenEncryptedResponseAlg")) { + JWEAlgorithm alg = JWEAlgorithm.parse(reader.nextString()); + client.setIdTokenEncryptedResponseAlg(alg); + } else if (name.equals("idTokenEncryptedResponseEnc")) { + EncryptionMethod alg = EncryptionMethod.parse(reader.nextString()); + client.setIdTokenEncryptedResponseEnc(alg); + } else if (name.equals("tokenEndpointAuthSigningAlg")) { + JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); + client.setTokenEndpointAuthSigningAlg(alg); + } else if (name.equals("defaultMaxAge")) { + client.setDefaultMaxAge(reader.nextInt()); + } else if (name.equals("requireAuthTime")) { + client.setRequireAuthTime(reader.nextBoolean()); + } else if (name.equals("defaultACRValues")) { + Set defaultACRvalues = readSet(reader); + client.setDefaultACRvalues(defaultACRvalues); + } else if (name.equals("initiateLoginUri")) { + client.setInitiateLoginUri(reader.nextString()); + } else if (name.equals("postLogoutRedirectUri")) { + HashSet postLogoutUris = Sets.newHashSet(reader.nextString()); + client.setPostLogoutRedirectUris(postLogoutUris); + } else if (name.equals("requestUris")) { + Set requestUris = readSet(reader); + client.setRequestUris(requestUris); + } else if (name.equals("description")) { + client.setClientDescription(reader.nextString()); + } else if (name.equals("allowIntrospection")) { + client.setAllowIntrospection(reader.nextBoolean()); + } else if (name.equals("reuseRefreshToken")) { + client.setReuseRefreshToken(reader.nextBoolean()); + } else if (name.equals("dynamicallyRegistered")) { + client.setDynamicallyRegistered(reader.nextBoolean()); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); } - client.setAuthorities(authorities); - } else if (name.equals("accessTokenValiditySeconds")) { - client.setAccessTokenValiditySeconds(reader.nextInt()); - } else if (name.equals("refreshTokenValiditySeconds")) { - client.setRefreshTokenValiditySeconds(reader.nextInt()); - } else if (name.equals("redirectUris")) { - Set redirectUris = readSet(reader); - client.setRedirectUris(redirectUris); - } else if (name.equals("name")) { - client.setClientName(reader.nextString()); - } else if (name.equals("uri")) { - client.setClientUri(reader.nextString()); - } else if (name.equals("logoUri")) { - client.setLogoUri(reader.nextString()); - } else if (name.equals("contacts")) { - Set contacts = readSet(reader); - client.setContacts(contacts); - } else if (name.equals("tosUri")) { - client.setTosUri(reader.nextString()); - } else if (name.equals("tokenEndpointAuthMethod")) { - AuthMethod am = AuthMethod.getByValue(reader.nextString()); - client.setTokenEndpointAuthMethod(am); - } else if (name.equals("grantTypes")) { - Set grantTypes = readSet(reader); - client.setGrantTypes(grantTypes); - } else if (name.equals("responseTypes")) { - Set responseTypes = readSet(reader); - client.setResponseTypes(responseTypes); - } else if (name.equals("policyUri")) { - client.setPolicyUri(reader.nextString()); - } else if (name.equals("applicationType")) { - AppType appType = AppType.getByValue(reader.nextString()); - client.setApplicationType(appType); - } else if (name.equals("sectorIdentifierUri")) { - client.setSectorIdentifierUri(reader.nextString()); - } else if (name.equals("subjectType")) { - SubjectType st = SubjectType.getByValue(reader.nextString()); - client.setSubjectType(st); - } else if (name.equals("jwks_uri")) { - client.setJwksUri(reader.nextString()); - } else if (name.equals("requestObjectSigningAlg")) { - JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); - client.setRequestObjectSigningAlg(alg); - } else if (name.equals("userInfoEncryptedResponseAlg")) { - JWEAlgorithm alg = JWEAlgorithm.parse(reader.nextString()); - client.setUserInfoEncryptedResponseAlg(alg); - } else if (name.equals("userInfoEncryptedResponseEnc")) { - EncryptionMethod alg = EncryptionMethod.parse(reader.nextString()); - client.setUserInfoEncryptedResponseEnc(alg); - } else if (name.equals("userInfoSignedResponseAlg")) { - JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); - client.setUserInfoSignedResponseAlg(alg); - } else if (name.equals("idTokenSignedResonseAlg")) { - JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); - client.setIdTokenSignedResponseAlg(alg); - } else if (name.equals("idTokenEncryptedResponseAlg")) { - JWEAlgorithm alg = JWEAlgorithm.parse(reader.nextString()); - client.setIdTokenEncryptedResponseAlg(alg); - } else if (name.equals("idTokenEncryptedResponseEnc")) { - EncryptionMethod alg = EncryptionMethod.parse(reader.nextString()); - client.setIdTokenEncryptedResponseEnc(alg); - } else if (name.equals("tokenEndpointAuthSigningAlg")) { - JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); - client.setTokenEndpointAuthSigningAlg(alg); - } else if (name.equals("defaultMaxAge")) { - client.setDefaultMaxAge(reader.nextInt()); - } else if (name.equals("requireAuthTime")) { - client.setRequireAuthTime(reader.nextBoolean()); - } else if (name.equals("defaultACRValues")) { - Set defaultACRvalues = readSet(reader); - client.setDefaultACRvalues(defaultACRvalues); - } else if (name.equals("initiateLoginUri")) { - client.setInitiateLoginUri(reader.nextString()); - } else if (name.equals("postLogoutRedirectUri")) { - HashSet postLogoutUris = Sets.newHashSet(reader.nextString()); - client.setPostLogoutRedirectUris(postLogoutUris); - } else if (name.equals("requestUris")) { - Set requestUris = readSet(reader); - client.setRequestUris(requestUris); - } else if (name.equals("description")) { - client.setClientDescription(reader.nextString()); - } else if (name.equals("allowIntrospection")) { - client.setAllowIntrospection(reader.nextBoolean()); - } else if (name.equals("reuseRefreshToken")) { - client.setReuseRefreshToken(reader.nextBoolean()); - } else if (name.equals("dynamicallyRegistered")) { - client.setDynamicallyRegistered(reader.nextBoolean()); - } else { + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -805,32 +805,32 @@ private void readSystemScopes(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals("value")) { - scope.setValue(reader.nextString()); - } else if (name.equals("description")) { - scope.setDescription(reader.nextString()); - } else if (name.equals("allowDynReg")) { - // previously "allowDynReg" scopes are now tagged as "not restricted" and vice versa - scope.setRestricted(!reader.nextBoolean()); - } else if (name.equals("defaultScope")) { - scope.setDefaultScope(reader.nextBoolean()); - } else if (name.equals("icon")) { - scope.setIcon(reader.nextString()); - } else { - logger.debug("found unexpected entry"); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals("value")) { + scope.setValue(reader.nextString()); + } else if (name.equals("description")) { + scope.setDescription(reader.nextString()); + } else if (name.equals("allowDynReg")) { + // previously "allowDynReg" scopes are now tagged as "not restricted" and vice versa + scope.setRestricted(!reader.nextBoolean()); + } else if (name.equals("defaultScope")) { + scope.setDefaultScope(reader.nextBoolean()); + } else if (name.equals("icon")) { + scope.setIcon(reader.nextString()); + } else { + logger.debug("found unexpected entry"); + reader.skipValue(); + } + break; + default: + logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -897,7 +897,7 @@ private void fixObjectReferences() { token.setApprovedSite(site); tokenRepository.saveAccessToken(token); } - + approvedSiteRepository.save(site); } } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_1.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_1.java index 0edc3aea2e..2bb76b0bf5 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_1.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_1.java @@ -16,6 +16,9 @@ *******************************************************************************/ package org.mitre.openid.connect.service.impl; +import static org.mitre.util.JsonUtils.readMap; +import static org.mitre.util.JsonUtils.readSet; + import java.io.IOException; import java.io.Serializable; import java.text.ParseException; @@ -71,9 +74,6 @@ import com.nimbusds.jose.JWSAlgorithm; import com.nimbusds.jwt.JWTParser; -import static org.mitre.util.JsonUtils.readMap; -import static org.mitre.util.JsonUtils.readSet; - /** * * Data service to import MITREid 1.1 configuration. @@ -107,8 +107,8 @@ public class MITREidDataService_1_1 extends MITREidDataServiceSupport implements private List extensions = Collections.emptyList(); private static final String THIS_VERSION = MITREID_CONNECT_1_1; - - private MITREidDataServiceMaps maps = new MITREidDataServiceMaps(); + + private MITREidDataServiceMaps maps = new MITREidDataServiceMaps(); @Override public boolean supportsVersion(String version) { @@ -137,46 +137,46 @@ public void importData(JsonReader reader) throws IOException { while (reader.hasNext()) { JsonToken tok = reader.peek(); switch (tok) { - case NAME: - String name = reader.nextName(); - // find out which member it is - if (name.equals(CLIENTS)) { - readClients(reader); - } else if (name.equals(GRANTS)) { - readGrants(reader); - } else if (name.equals(WHITELISTEDSITES)) { - readWhitelistedSites(reader); - } else if (name.equals(BLACKLISTEDSITES)) { - readBlacklistedSites(reader); - } else if (name.equals(AUTHENTICATIONHOLDERS)) { - readAuthenticationHolders(reader); - } else if (name.equals(ACCESSTOKENS)) { - readAccessTokens(reader); - } else if (name.equals(REFRESHTOKENS)) { - readRefreshTokens(reader); - } else if (name.equals(SYSTEMSCOPES)) { - readSystemScopes(reader); - } else { - for (MITREidDataServiceExtension extension : extensions) { - if (extension.supportsVersion(THIS_VERSION)) { + case NAME: + String name = reader.nextName(); + // find out which member it is + if (name.equals(CLIENTS)) { + readClients(reader); + } else if (name.equals(GRANTS)) { + readGrants(reader); + } else if (name.equals(WHITELISTEDSITES)) { + readWhitelistedSites(reader); + } else if (name.equals(BLACKLISTEDSITES)) { + readBlacklistedSites(reader); + } else if (name.equals(AUTHENTICATIONHOLDERS)) { + readAuthenticationHolders(reader); + } else if (name.equals(ACCESSTOKENS)) { + readAccessTokens(reader); + } else if (name.equals(REFRESHTOKENS)) { + readRefreshTokens(reader); + } else if (name.equals(SYSTEMSCOPES)) { + readSystemScopes(reader); + } else { + for (MITREidDataServiceExtension extension : extensions) { if (extension.supportsVersion(THIS_VERSION)) { - extension.importExtensionData(name, reader); - break; + if (extension.supportsVersion(THIS_VERSION)) { + extension.importExtensionData(name, reader); + break; + } } } + // unknown token, skip it + reader.skipValue(); } - // unknown token, skip it + break; + case END_OBJECT: + // the object ended, we're done here + reader.endObject(); + continue; + default: + logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - case END_OBJECT: - // the object ended, we're done here - reader.endObject(); - continue; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } fixObjectReferences(); @@ -206,37 +206,37 @@ private void readRefreshTokens(JsonReader reader) throws IOException { Long authHolderId = null; while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals("id")) { - currentId = reader.nextLong(); - } else if (name.equals("expiration")) { - Date date = utcToDate(reader.nextString()); - token.setExpiration(date); - } else if (name.equals("value")) { - String value = reader.nextString(); - try { - token.setJwt(JWTParser.parse(value)); - } catch (ParseException ex) { - logger.error("Unable to set refresh token value to {}", value, ex); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals("id")) { + currentId = reader.nextLong(); + } else if (name.equals("expiration")) { + Date date = utcToDate(reader.nextString()); + token.setExpiration(date); + } else if (name.equals("value")) { + String value = reader.nextString(); + try { + token.setJwt(JWTParser.parse(value)); + } catch (ParseException ex) { + logger.error("Unable to set refresh token value to {}", value, ex); + } + } else if (name.equals("clientId")) { + clientId = reader.nextString(); + } else if (name.equals("authenticationHolderId")) { + authHolderId = reader.nextLong(); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); } - } else if (name.equals("clientId")) { - clientId = reader.nextString(); - } else if (name.equals("authenticationHolderId")) { - authHolderId = reader.nextLong(); - } else { + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -268,45 +268,45 @@ private void readAccessTokens(JsonReader reader) throws IOException { Long refreshTokenId = null; while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals("id")) { - currentId = reader.nextLong(); - } else if (name.equals("expiration")) { - Date date = utcToDate(reader.nextString()); - token.setExpiration(date); - } else if (name.equals("value")) { - String value = reader.nextString(); - try { - // all tokens are JWTs - token.setJwt(JWTParser.parse(value)); - } catch (ParseException ex) { - logger.error("Unable to set refresh token value to {}", value, ex); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals("id")) { + currentId = reader.nextLong(); + } else if (name.equals("expiration")) { + Date date = utcToDate(reader.nextString()); + token.setExpiration(date); + } else if (name.equals("value")) { + String value = reader.nextString(); + try { + // all tokens are JWTs + token.setJwt(JWTParser.parse(value)); + } catch (ParseException ex) { + logger.error("Unable to set refresh token value to {}", value, ex); + } + } else if (name.equals("clientId")) { + clientId = reader.nextString(); + } else if (name.equals("authenticationHolderId")) { + authHolderId = reader.nextLong(); + } else if (name.equals("refreshTokenId")) { + refreshTokenId = reader.nextLong(); + } else if (name.equals("scope")) { + Set scope = readSet(reader); + token.setScope(scope); + } else if (name.equals("type")) { + token.setTokenType(reader.nextString()); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); } - } else if (name.equals("clientId")) { - clientId = reader.nextString(); - } else if (name.equals("authenticationHolderId")) { - authHolderId = reader.nextLong(); - } else if (name.equals("refreshTokenId")) { - refreshTokenId = reader.nextLong(); - } else if (name.equals("scope")) { - Set scope = readSet(reader); - token.setScope(scope); - } else if (name.equals("type")) { - token.setTokenType(reader.nextString()); - } else { + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -334,61 +334,61 @@ private void readAuthenticationHolders(JsonReader reader) throws IOException { Long currentId = null; while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals("id")) { - currentId = reader.nextLong(); - } else if (name.equals("ownerId")) { - //not needed - reader.skipValue(); - } else if (name.equals("authentication")) { - OAuth2Request clientAuthorization = null; - Authentication userAuthentication = null; - reader.beginObject(); - while (reader.hasNext()) { - switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String subName = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); // skip null values - } else if (subName.equals("clientAuthorization")) { - clientAuthorization = readAuthorizationRequest(reader); - } else if (subName.equals("userAuthentication")) { - // skip binary encoded version - reader.skipValue(); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals("id")) { + currentId = reader.nextLong(); + } else if (name.equals("ownerId")) { + //not needed + reader.skipValue(); + } else if (name.equals("authentication")) { + OAuth2Request clientAuthorization = null; + Authentication userAuthentication = null; + reader.beginObject(); + while (reader.hasNext()) { + switch (reader.peek()) { + case END_OBJECT: + continue; + case NAME: + String subName = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); // skip null values + } else if (subName.equals("clientAuthorization")) { + clientAuthorization = readAuthorizationRequest(reader); + } else if (subName.equals("userAuthentication")) { + // skip binary encoded version + reader.skipValue(); - } else if (subName.equals("savedUserAuthentication")) { - userAuthentication = readSavedUserAuthentication(reader); + } else if (subName.equals("savedUserAuthentication")) { + userAuthentication = readSavedUserAuthentication(reader); - } else { - logger.debug("Found unexpected entry"); - reader.skipValue(); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); + } + break; + default: + logger.debug("Found unexpected entry"); + reader.skipValue(); + continue; } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; } + reader.endObject(); + OAuth2Authentication auth = new OAuth2Authentication(clientAuthorization, userAuthentication); + ahe.setAuthentication(auth); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); } - reader.endObject(); - OAuth2Authentication auth = new OAuth2Authentication(clientAuthorization, userAuthentication); - ahe.setAuthentication(auth); - } else { + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -414,53 +414,53 @@ private OAuth2Request readAuthorizationRequest(JsonReader reader) throws IOExcep reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals("requestParameters")) { - requestParameters = readMap(reader); - } else if (name.equals("clientId")) { - clientId = reader.nextString(); - } else if (name.equals("scope")) { - scope = readSet(reader); - } else if (name.equals("resourceIds")) { - resourceIds = readSet(reader); - } else if (name.equals("authorities")) { - Set authorityStrs = readSet(reader); - authorities = new HashSet<>(); - for (String s : authorityStrs) { - GrantedAuthority ga = new SimpleGrantedAuthority(s); - authorities.add(ga); - } - } else if (name.equals("approved")) { - approved = reader.nextBoolean(); - } else if (name.equals("denied")) { - if (approved == false) { - approved = !reader.nextBoolean(); - } - } else if (name.equals("redirectUri")) { - redirectUri = reader.nextString(); - } else if (name.equals("responseTypes")) { - responseTypes = readSet(reader); - } else if (name.equals("extensions")) { - // skip the binary encoded version - reader.skipValue(); - } else if (name.equals("extensionStrings")) { - Map extEnc = readMap(reader); - for (Entry entry : extEnc.entrySet()) { - extensions.put(entry.getKey(), entry.getValue()); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals("requestParameters")) { + requestParameters = readMap(reader); + } else if (name.equals("clientId")) { + clientId = reader.nextString(); + } else if (name.equals("scope")) { + scope = readSet(reader); + } else if (name.equals("resourceIds")) { + resourceIds = readSet(reader); + } else if (name.equals("authorities")) { + Set authorityStrs = readSet(reader); + authorities = new HashSet<>(); + for (String s : authorityStrs) { + GrantedAuthority ga = new SimpleGrantedAuthority(s); + authorities.add(ga); + } + } else if (name.equals("approved")) { + approved = reader.nextBoolean(); + } else if (name.equals("denied")) { + if (approved == false) { + approved = !reader.nextBoolean(); + } + } else if (name.equals("redirectUri")) { + redirectUri = reader.nextString(); + } else if (name.equals("responseTypes")) { + responseTypes = readSet(reader); + } else if (name.equals("extensions")) { + // skip the binary encoded version + reader.skipValue(); + } else if (name.equals("extensionStrings")) { + Map extEnc = readMap(reader); + for (Entry entry : extEnc.entrySet()) { + extensions.put(entry.getKey(), entry.getValue()); + } + } else { + reader.skipValue(); } - } else { + break; + default: + logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -478,35 +478,35 @@ private SavedUserAuthentication readSavedUserAuthentication(JsonReader reader) t while (reader.hasNext()) { switch(reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals("name")) { - savedUserAuth.setName(reader.nextString()); - } else if (name.equals("sourceClass")) { - savedUserAuth.setSourceClass(reader.nextString()); - } else if (name.equals("authenticated")) { - savedUserAuth.setAuthenticated(reader.nextBoolean()); - } else if (name.equals("authorities")) { - Set authorityStrs = readSet(reader); - Set authorities = new HashSet(); - for (String s : authorityStrs) { - GrantedAuthority ga = new SimpleGrantedAuthority(s); - authorities.add(ga); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals("name")) { + savedUserAuth.setName(reader.nextString()); + } else if (name.equals("sourceClass")) { + savedUserAuth.setSourceClass(reader.nextString()); + } else if (name.equals("authenticated")) { + savedUserAuth.setAuthenticated(reader.nextBoolean()); + } else if (name.equals("authorities")) { + Set authorityStrs = readSet(reader); + Set authorities = new HashSet(); + for (String s : authorityStrs) { + GrantedAuthority ga = new SimpleGrantedAuthority(s); + authorities.add(ga); + } + savedUserAuth.setAuthorities(authorities); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); } - savedUserAuth.setAuthorities(authorities); - } else { + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } @@ -528,43 +528,43 @@ private void readGrants(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals("id")) { - currentId = reader.nextLong(); - } else if (name.equals("accessDate")) { - Date date = utcToDate(reader.nextString()); - site.setAccessDate(date); - } else if (name.equals("clientId")) { - site.setClientId(reader.nextString()); - } else if (name.equals("creationDate")) { - Date date = utcToDate(reader.nextString()); - site.setCreationDate(date); - } else if (name.equals("timeoutDate")) { - Date date = utcToDate(reader.nextString()); - site.setTimeoutDate(date); - } else if (name.equals("userId")) { - site.setUserId(reader.nextString()); - } else if (name.equals("allowedScopes")) { - Set allowedScopes = readSet(reader); - site.setAllowedScopes(allowedScopes); - } else if (name.equals("whitelistedSiteId")) { - whitelistedSiteId = reader.nextLong(); - } else if (name.equals("approvedAccessTokens")) { - tokenIds = readSet(reader); - } else { + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals("id")) { + currentId = reader.nextLong(); + } else if (name.equals("accessDate")) { + Date date = utcToDate(reader.nextString()); + site.setAccessDate(date); + } else if (name.equals("clientId")) { + site.setClientId(reader.nextString()); + } else if (name.equals("creationDate")) { + Date date = utcToDate(reader.nextString()); + site.setCreationDate(date); + } else if (name.equals("timeoutDate")) { + Date date = utcToDate(reader.nextString()); + site.setTimeoutDate(date); + } else if (name.equals("userId")) { + site.setUserId(reader.nextString()); + } else if (name.equals("allowedScopes")) { + Set allowedScopes = readSet(reader); + site.setAllowedScopes(allowedScopes); + } else if (name.equals("whitelistedSiteId")) { + whitelistedSiteId = reader.nextLong(); + } else if (name.equals("approvedAccessTokens")) { + tokenIds = readSet(reader); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); + } + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -593,28 +593,28 @@ private void readWhitelistedSites(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (name.equals("id")) { - currentId = reader.nextLong(); - } else if (name.equals("clientId")) { - wlSite.setClientId(reader.nextString()); - } else if (name.equals("creatorUserId")) { - wlSite.setCreatorUserId(reader.nextString()); - } else if (name.equals("allowedScopes")) { - Set allowedScopes = readSet(reader); - wlSite.setAllowedScopes(allowedScopes); - } else { + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (name.equals("id")) { + currentId = reader.nextLong(); + } else if (name.equals("clientId")) { + wlSite.setClientId(reader.nextString()); + } else if (name.equals("creatorUserId")) { + wlSite.setCreatorUserId(reader.nextString()); + } else if (name.equals("allowedScopes")) { + Set allowedScopes = readSet(reader); + wlSite.setAllowedScopes(allowedScopes); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); + } + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -636,23 +636,23 @@ private void readBlacklistedSites(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (name.equals("id")) { - reader.skipValue(); - } else if (name.equals("uri")) { - blSite.setUri(reader.nextString()); - } else { + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (name.equals("id")) { + reader.skipValue(); + } else if (name.equals("uri")) { + blSite.setUri(reader.nextString()); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); + } + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -673,125 +673,125 @@ private void readClients(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals("clientId")) { - client.setClientId(reader.nextString()); - } else if (name.equals("resourceIds")) { - Set resourceIds = readSet(reader); - client.setResourceIds(resourceIds); - } else if (name.equals("secret")) { - client.setClientSecret(reader.nextString()); - } else if (name.equals("scope")) { - Set scope = readSet(reader); - client.setScope(scope); - } else if (name.equals("authorities")) { - Set authorityStrs = readSet(reader); - Set authorities = new HashSet<>(); - for (String s : authorityStrs) { - GrantedAuthority ga = new SimpleGrantedAuthority(s); - authorities.add(ga); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals("clientId")) { + client.setClientId(reader.nextString()); + } else if (name.equals("resourceIds")) { + Set resourceIds = readSet(reader); + client.setResourceIds(resourceIds); + } else if (name.equals("secret")) { + client.setClientSecret(reader.nextString()); + } else if (name.equals("scope")) { + Set scope = readSet(reader); + client.setScope(scope); + } else if (name.equals("authorities")) { + Set authorityStrs = readSet(reader); + Set authorities = new HashSet<>(); + for (String s : authorityStrs) { + GrantedAuthority ga = new SimpleGrantedAuthority(s); + authorities.add(ga); + } + client.setAuthorities(authorities); + } else if (name.equals("accessTokenValiditySeconds")) { + client.setAccessTokenValiditySeconds(reader.nextInt()); + } else if (name.equals("refreshTokenValiditySeconds")) { + client.setRefreshTokenValiditySeconds(reader.nextInt()); + } else if (name.equals("redirectUris")) { + Set redirectUris = readSet(reader); + client.setRedirectUris(redirectUris); + } else if (name.equals("name")) { + client.setClientName(reader.nextString()); + } else if (name.equals("uri")) { + client.setClientUri(reader.nextString()); + } else if (name.equals("logoUri")) { + client.setLogoUri(reader.nextString()); + } else if (name.equals("contacts")) { + Set contacts = readSet(reader); + client.setContacts(contacts); + } else if (name.equals("tosUri")) { + client.setTosUri(reader.nextString()); + } else if (name.equals("tokenEndpointAuthMethod")) { + AuthMethod am = AuthMethod.getByValue(reader.nextString()); + client.setTokenEndpointAuthMethod(am); + } else if (name.equals("grantTypes")) { + Set grantTypes = readSet(reader); + client.setGrantTypes(grantTypes); + } else if (name.equals("responseTypes")) { + Set responseTypes = readSet(reader); + client.setResponseTypes(responseTypes); + } else if (name.equals("policyUri")) { + client.setPolicyUri(reader.nextString()); + } else if (name.equals("applicationType")) { + AppType appType = AppType.getByValue(reader.nextString()); + client.setApplicationType(appType); + } else if (name.equals("sectorIdentifierUri")) { + client.setSectorIdentifierUri(reader.nextString()); + } else if (name.equals("subjectType")) { + SubjectType st = SubjectType.getByValue(reader.nextString()); + client.setSubjectType(st); + } else if (name.equals("jwks_uri")) { + client.setJwksUri(reader.nextString()); + } else if (name.equals("requestObjectSigningAlg")) { + JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); + client.setRequestObjectSigningAlg(alg); + } else if (name.equals("userInfoEncryptedResponseAlg")) { + JWEAlgorithm alg = JWEAlgorithm.parse(reader.nextString()); + client.setUserInfoEncryptedResponseAlg(alg); + } else if (name.equals("userInfoEncryptedResponseEnc")) { + EncryptionMethod alg = EncryptionMethod.parse(reader.nextString()); + client.setUserInfoEncryptedResponseEnc(alg); + } else if (name.equals("userInfoSignedResponseAlg")) { + JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); + client.setUserInfoSignedResponseAlg(alg); + } else if (name.equals("idTokenSignedResonseAlg")) { + JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); + client.setIdTokenSignedResponseAlg(alg); + } else if (name.equals("idTokenEncryptedResponseAlg")) { + JWEAlgorithm alg = JWEAlgorithm.parse(reader.nextString()); + client.setIdTokenEncryptedResponseAlg(alg); + } else if (name.equals("idTokenEncryptedResponseEnc")) { + EncryptionMethod alg = EncryptionMethod.parse(reader.nextString()); + client.setIdTokenEncryptedResponseEnc(alg); + } else if (name.equals("tokenEndpointAuthSigningAlg")) { + JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); + client.setTokenEndpointAuthSigningAlg(alg); + } else if (name.equals("defaultMaxAge")) { + client.setDefaultMaxAge(reader.nextInt()); + } else if (name.equals("requireAuthTime")) { + client.setRequireAuthTime(reader.nextBoolean()); + } else if (name.equals("defaultACRValues")) { + Set defaultACRvalues = readSet(reader); + client.setDefaultACRvalues(defaultACRvalues); + } else if (name.equals("initiateLoginUri")) { + client.setInitiateLoginUri(reader.nextString()); + } else if (name.equals("postLogoutRedirectUri")) { + HashSet postLogoutUris = Sets.newHashSet(reader.nextString()); + client.setPostLogoutRedirectUris(postLogoutUris); + } else if (name.equals("requestUris")) { + Set requestUris = readSet(reader); + client.setRequestUris(requestUris); + } else if (name.equals("description")) { + client.setClientDescription(reader.nextString()); + } else if (name.equals("allowIntrospection")) { + client.setAllowIntrospection(reader.nextBoolean()); + } else if (name.equals("reuseRefreshToken")) { + client.setReuseRefreshToken(reader.nextBoolean()); + } else if (name.equals("dynamicallyRegistered")) { + client.setDynamicallyRegistered(reader.nextBoolean()); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); } - client.setAuthorities(authorities); - } else if (name.equals("accessTokenValiditySeconds")) { - client.setAccessTokenValiditySeconds(reader.nextInt()); - } else if (name.equals("refreshTokenValiditySeconds")) { - client.setRefreshTokenValiditySeconds(reader.nextInt()); - } else if (name.equals("redirectUris")) { - Set redirectUris = readSet(reader); - client.setRedirectUris(redirectUris); - } else if (name.equals("name")) { - client.setClientName(reader.nextString()); - } else if (name.equals("uri")) { - client.setClientUri(reader.nextString()); - } else if (name.equals("logoUri")) { - client.setLogoUri(reader.nextString()); - } else if (name.equals("contacts")) { - Set contacts = readSet(reader); - client.setContacts(contacts); - } else if (name.equals("tosUri")) { - client.setTosUri(reader.nextString()); - } else if (name.equals("tokenEndpointAuthMethod")) { - AuthMethod am = AuthMethod.getByValue(reader.nextString()); - client.setTokenEndpointAuthMethod(am); - } else if (name.equals("grantTypes")) { - Set grantTypes = readSet(reader); - client.setGrantTypes(grantTypes); - } else if (name.equals("responseTypes")) { - Set responseTypes = readSet(reader); - client.setResponseTypes(responseTypes); - } else if (name.equals("policyUri")) { - client.setPolicyUri(reader.nextString()); - } else if (name.equals("applicationType")) { - AppType appType = AppType.getByValue(reader.nextString()); - client.setApplicationType(appType); - } else if (name.equals("sectorIdentifierUri")) { - client.setSectorIdentifierUri(reader.nextString()); - } else if (name.equals("subjectType")) { - SubjectType st = SubjectType.getByValue(reader.nextString()); - client.setSubjectType(st); - } else if (name.equals("jwks_uri")) { - client.setJwksUri(reader.nextString()); - } else if (name.equals("requestObjectSigningAlg")) { - JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); - client.setRequestObjectSigningAlg(alg); - } else if (name.equals("userInfoEncryptedResponseAlg")) { - JWEAlgorithm alg = JWEAlgorithm.parse(reader.nextString()); - client.setUserInfoEncryptedResponseAlg(alg); - } else if (name.equals("userInfoEncryptedResponseEnc")) { - EncryptionMethod alg = EncryptionMethod.parse(reader.nextString()); - client.setUserInfoEncryptedResponseEnc(alg); - } else if (name.equals("userInfoSignedResponseAlg")) { - JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); - client.setUserInfoSignedResponseAlg(alg); - } else if (name.equals("idTokenSignedResonseAlg")) { - JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); - client.setIdTokenSignedResponseAlg(alg); - } else if (name.equals("idTokenEncryptedResponseAlg")) { - JWEAlgorithm alg = JWEAlgorithm.parse(reader.nextString()); - client.setIdTokenEncryptedResponseAlg(alg); - } else if (name.equals("idTokenEncryptedResponseEnc")) { - EncryptionMethod alg = EncryptionMethod.parse(reader.nextString()); - client.setIdTokenEncryptedResponseEnc(alg); - } else if (name.equals("tokenEndpointAuthSigningAlg")) { - JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); - client.setTokenEndpointAuthSigningAlg(alg); - } else if (name.equals("defaultMaxAge")) { - client.setDefaultMaxAge(reader.nextInt()); - } else if (name.equals("requireAuthTime")) { - client.setRequireAuthTime(reader.nextBoolean()); - } else if (name.equals("defaultACRValues")) { - Set defaultACRvalues = readSet(reader); - client.setDefaultACRvalues(defaultACRvalues); - } else if (name.equals("initiateLoginUri")) { - client.setInitiateLoginUri(reader.nextString()); - } else if (name.equals("postLogoutRedirectUri")) { - HashSet postLogoutUris = Sets.newHashSet(reader.nextString()); - client.setPostLogoutRedirectUris(postLogoutUris); - } else if (name.equals("requestUris")) { - Set requestUris = readSet(reader); - client.setRequestUris(requestUris); - } else if (name.equals("description")) { - client.setClientDescription(reader.nextString()); - } else if (name.equals("allowIntrospection")) { - client.setAllowIntrospection(reader.nextBoolean()); - } else if (name.equals("reuseRefreshToken")) { - client.setReuseRefreshToken(reader.nextBoolean()); - } else if (name.equals("dynamicallyRegistered")) { - client.setDynamicallyRegistered(reader.nextBoolean()); - } else { + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -815,36 +815,36 @@ private void readSystemScopes(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals("value")) { - scope.setValue(reader.nextString()); - } else if (name.equals("description")) { - scope.setDescription(reader.nextString()); - } else if (name.equals("allowDynReg")) { - // previously "allowDynReg" scopes are now tagged as "not restricted" and vice versa - scope.setRestricted(!reader.nextBoolean()); - } else if (name.equals("defaultScope")) { - scope.setDefaultScope(reader.nextBoolean()); - } else if (name.equals("structured")) { - logger.warn("Found a structured scope, ignoring structure"); - } else if (name.equals("structuredParameter")) { - logger.warn("Found a structured scope, ignoring structure"); - } else if (name.equals("icon")) { - scope.setIcon(reader.nextString()); - } else { - logger.debug("found unexpected entry"); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals("value")) { + scope.setValue(reader.nextString()); + } else if (name.equals("description")) { + scope.setDescription(reader.nextString()); + } else if (name.equals("allowDynReg")) { + // previously "allowDynReg" scopes are now tagged as "not restricted" and vice versa + scope.setRestricted(!reader.nextBoolean()); + } else if (name.equals("defaultScope")) { + scope.setDefaultScope(reader.nextBoolean()); + } else if (name.equals("structured")) { + logger.warn("Found a structured scope, ignoring structure"); + } else if (name.equals("structuredParameter")) { + logger.warn("Found a structured scope, ignoring structure"); + } else if (name.equals("icon")) { + scope.setIcon(reader.nextString()); + } else { + logger.debug("found unexpected entry"); + reader.skipValue(); + } + break; + default: + logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -911,7 +911,7 @@ private void fixObjectReferences() { token.setApprovedSite(site); tokenRepository.saveAccessToken(token); } - + approvedSiteRepository.save(site); } } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_2.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_2.java index b5f184c3b0..aeffbfa39f 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_2.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_2.java @@ -16,16 +16,15 @@ *******************************************************************************/ package org.mitre.openid.connect.service.impl; +import static org.mitre.util.JsonUtils.readMap; +import static org.mitre.util.JsonUtils.readSet; + import java.io.IOException; -import java.io.Serializable; import java.text.ParseException; import java.util.Collections; import java.util.Date; -import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; import java.util.Set; import org.mitre.oauth2.model.AuthenticationHolderEntity; @@ -66,10 +65,6 @@ import com.nimbusds.jose.jwk.JWKSet; import com.nimbusds.jwt.JWTParser; -import static org.mitre.util.JsonUtils.readMap; -import static org.mitre.util.JsonUtils.readSet; -import static org.mitre.util.JsonUtils.writeNullSafeArray; - /** * * Data service to import and export MITREid 1.2 configuration. @@ -169,10 +164,10 @@ public class MITREidDataService_1_2 extends MITREidDataServiceSupport implements @Autowired(required = false) private List extensions = Collections.emptyList(); - private MITREidDataServiceMaps maps = new MITREidDataServiceMaps(); + private MITREidDataServiceMaps maps = new MITREidDataServiceMaps(); private static final String THIS_VERSION = MITREID_CONNECT_1_2; - + @Override public boolean supportsVersion(String version) { return THIS_VERSION.equals(version); @@ -201,44 +196,44 @@ public void importData(JsonReader reader) throws IOException { while (reader.hasNext()) { JsonToken tok = reader.peek(); switch (tok) { - case NAME: - String name = reader.nextName(); - // find out which member it is - if (name.equals(CLIENTS)) { - readClients(reader); - } else if (name.equals(GRANTS)) { - readGrants(reader); - } else if (name.equals(WHITELISTEDSITES)) { - readWhitelistedSites(reader); - } else if (name.equals(BLACKLISTEDSITES)) { - readBlacklistedSites(reader); - } else if (name.equals(AUTHENTICATIONHOLDERS)) { - readAuthenticationHolders(reader); - } else if (name.equals(ACCESSTOKENS)) { - readAccessTokens(reader); - } else if (name.equals(REFRESHTOKENS)) { - readRefreshTokens(reader); - } else if (name.equals(SYSTEMSCOPES)) { - readSystemScopes(reader); - } else { - for (MITREidDataServiceExtension extension : extensions) { - if (extension.supportsVersion(THIS_VERSION)) { - extension.importExtensionData(name, reader); - break; + case NAME: + String name = reader.nextName(); + // find out which member it is + if (name.equals(CLIENTS)) { + readClients(reader); + } else if (name.equals(GRANTS)) { + readGrants(reader); + } else if (name.equals(WHITELISTEDSITES)) { + readWhitelistedSites(reader); + } else if (name.equals(BLACKLISTEDSITES)) { + readBlacklistedSites(reader); + } else if (name.equals(AUTHENTICATIONHOLDERS)) { + readAuthenticationHolders(reader); + } else if (name.equals(ACCESSTOKENS)) { + readAccessTokens(reader); + } else if (name.equals(REFRESHTOKENS)) { + readRefreshTokens(reader); + } else if (name.equals(SYSTEMSCOPES)) { + readSystemScopes(reader); + } else { + for (MITREidDataServiceExtension extension : extensions) { + if (extension.supportsVersion(THIS_VERSION)) { + extension.importExtensionData(name, reader); + break; + } } + // unknown token, skip it + reader.skipValue(); } - // unknown token, skip it + break; + case END_OBJECT: + // the object ended, we're done here + reader.endObject(); + continue; + default: + logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - case END_OBJECT: - // the object ended, we're done here - reader.endObject(); - continue; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } fixObjectReferences(); @@ -268,37 +263,37 @@ private void readRefreshTokens(JsonReader reader) throws IOException { Long authHolderId = null; while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals(ID)) { - currentId = reader.nextLong(); - } else if (name.equals(EXPIRATION)) { - Date date = utcToDate(reader.nextString()); - token.setExpiration(date); - } else if (name.equals(VALUE)) { - String value = reader.nextString(); - try { - token.setJwt(JWTParser.parse(value)); - } catch (ParseException ex) { - logger.error("Unable to set refresh token value to {}", value, ex); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals(ID)) { + currentId = reader.nextLong(); + } else if (name.equals(EXPIRATION)) { + Date date = utcToDate(reader.nextString()); + token.setExpiration(date); + } else if (name.equals(VALUE)) { + String value = reader.nextString(); + try { + token.setJwt(JWTParser.parse(value)); + } catch (ParseException ex) { + logger.error("Unable to set refresh token value to {}", value, ex); + } + } else if (name.equals(CLIENT_ID)) { + clientId = reader.nextString(); + } else if (name.equals(AUTHENTICATION_HOLDER_ID)) { + authHolderId = reader.nextLong(); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); } - } else if (name.equals(CLIENT_ID)) { - clientId = reader.nextString(); - } else if (name.equals(AUTHENTICATION_HOLDER_ID)) { - authHolderId = reader.nextLong(); - } else { + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -330,45 +325,45 @@ private void readAccessTokens(JsonReader reader) throws IOException { Long refreshTokenId = null; while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals(ID)) { - currentId = reader.nextLong(); - } else if (name.equals(EXPIRATION)) { - Date date = utcToDate(reader.nextString()); - token.setExpiration(date); - } else if (name.equals(VALUE)) { - String value = reader.nextString(); - try { - // all tokens are JWTs - token.setJwt(JWTParser.parse(value)); - } catch (ParseException ex) { - logger.error("Unable to set refresh token value to {}", value, ex); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals(ID)) { + currentId = reader.nextLong(); + } else if (name.equals(EXPIRATION)) { + Date date = utcToDate(reader.nextString()); + token.setExpiration(date); + } else if (name.equals(VALUE)) { + String value = reader.nextString(); + try { + // all tokens are JWTs + token.setJwt(JWTParser.parse(value)); + } catch (ParseException ex) { + logger.error("Unable to set refresh token value to {}", value, ex); + } + } else if (name.equals(CLIENT_ID)) { + clientId = reader.nextString(); + } else if (name.equals(AUTHENTICATION_HOLDER_ID)) { + authHolderId = reader.nextLong(); + } else if (name.equals(REFRESH_TOKEN_ID)) { + refreshTokenId = reader.nextLong(); + } else if (name.equals(SCOPE)) { + Set scope = readSet(reader); + token.setScope(scope); + } else if (name.equals(TYPE)) { + token.setTokenType(reader.nextString()); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); } - } else if (name.equals(CLIENT_ID)) { - clientId = reader.nextString(); - } else if (name.equals(AUTHENTICATION_HOLDER_ID)) { - authHolderId = reader.nextLong(); - } else if (name.equals(REFRESH_TOKEN_ID)) { - refreshTokenId = reader.nextLong(); - } else if (name.equals(SCOPE)) { - Set scope = readSet(reader); - token.setScope(scope); - } else if (name.equals(TYPE)) { - token.setTokenType(reader.nextString()); - } else { + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -396,49 +391,49 @@ private void readAuthenticationHolders(JsonReader reader) throws IOException { Long currentId = null; while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals(ID)) { - currentId = reader.nextLong(); - } else if (name.equals(REQUEST_PARAMETERS)) { - ahe.setRequestParameters(readMap(reader)); - } else if (name.equals(CLIENT_ID)) { - ahe.setClientId(reader.nextString()); - } else if (name.equals(SCOPE)) { - ahe.setScope(readSet(reader)); - } else if (name.equals(RESOURCE_IDS)) { - ahe.setResourceIds(readSet(reader)); - } else if (name.equals(AUTHORITIES)) { - Set authorityStrs = readSet(reader); - Set authorities = new HashSet(); - for (String s : authorityStrs) { - GrantedAuthority ga = new SimpleGrantedAuthority(s); - authorities.add(ga); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals(ID)) { + currentId = reader.nextLong(); + } else if (name.equals(REQUEST_PARAMETERS)) { + ahe.setRequestParameters(readMap(reader)); + } else if (name.equals(CLIENT_ID)) { + ahe.setClientId(reader.nextString()); + } else if (name.equals(SCOPE)) { + ahe.setScope(readSet(reader)); + } else if (name.equals(RESOURCE_IDS)) { + ahe.setResourceIds(readSet(reader)); + } else if (name.equals(AUTHORITIES)) { + Set authorityStrs = readSet(reader); + Set authorities = new HashSet(); + for (String s : authorityStrs) { + GrantedAuthority ga = new SimpleGrantedAuthority(s); + authorities.add(ga); + } + ahe.setAuthorities(authorities); + } else if (name.equals(APPROVED)) { + ahe.setApproved(reader.nextBoolean()); + } else if (name.equals(REDIRECT_URI)) { + ahe.setRedirectUri(reader.nextString()); + } else if (name.equals(RESPONSE_TYPES)) { + ahe.setResponseTypes(readSet(reader)); + } else if (name.equals(EXTENSIONS)) { + ahe.setExtensions(readMap(reader)); + } else if (name.equals(SAVED_USER_AUTHENTICATION)) { + ahe.setUserAuth(readSavedUserAuthentication(reader)); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); } - ahe.setAuthorities(authorities); - } else if (name.equals(APPROVED)) { - ahe.setApproved(reader.nextBoolean()); - } else if (name.equals(REDIRECT_URI)) { - ahe.setRedirectUri(reader.nextString()); - } else if (name.equals(RESPONSE_TYPES)) { - ahe.setResponseTypes(readSet(reader)); - } else if (name.equals(EXTENSIONS)) { - ahe.setExtensions(readMap(reader)); - } else if (name.equals(SAVED_USER_AUTHENTICATION)) { - ahe.setUserAuth(readSavedUserAuthentication(reader)); - } else { + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -461,35 +456,35 @@ private SavedUserAuthentication readSavedUserAuthentication(JsonReader reader) t while (reader.hasNext()) { switch(reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals(NAME)) { - savedUserAuth.setName(reader.nextString()); - } else if (name.equals(SOURCE_CLASS)) { - savedUserAuth.setSourceClass(reader.nextString()); - } else if (name.equals(AUTHENTICATED)) { - savedUserAuth.setAuthenticated(reader.nextBoolean()); - } else if (name.equals(AUTHORITIES)) { - Set authorityStrs = readSet(reader); - Set authorities = new HashSet(); - for (String s : authorityStrs) { - GrantedAuthority ga = new SimpleGrantedAuthority(s); - authorities.add(ga); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals(NAME)) { + savedUserAuth.setName(reader.nextString()); + } else if (name.equals(SOURCE_CLASS)) { + savedUserAuth.setSourceClass(reader.nextString()); + } else if (name.equals(AUTHENTICATED)) { + savedUserAuth.setAuthenticated(reader.nextBoolean()); + } else if (name.equals(AUTHORITIES)) { + Set authorityStrs = readSet(reader); + Set authorities = new HashSet(); + for (String s : authorityStrs) { + GrantedAuthority ga = new SimpleGrantedAuthority(s); + authorities.add(ga); + } + savedUserAuth.setAuthorities(authorities); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); } - savedUserAuth.setAuthorities(authorities); - } else { + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } @@ -510,41 +505,41 @@ private void readGrants(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals(ID)) { - currentId = reader.nextLong(); - } else if (name.equals(ACCESS_DATE)) { - Date date = utcToDate(reader.nextString()); - site.setAccessDate(date); - } else if (name.equals(CLIENT_ID)) { - site.setClientId(reader.nextString()); - } else if (name.equals(CREATION_DATE)) { - Date date = utcToDate(reader.nextString()); - site.setCreationDate(date); - } else if (name.equals(TIMEOUT_DATE)) { - Date date = utcToDate(reader.nextString()); - site.setTimeoutDate(date); - } else if (name.equals(USER_ID)) { - site.setUserId(reader.nextString()); - } else if (name.equals(ALLOWED_SCOPES)) { - Set allowedScopes = readSet(reader); - site.setAllowedScopes(allowedScopes); - } else if (name.equals(APPROVED_ACCESS_TOKENS)) { - tokenIds = readSet(reader); - } else { + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals(ID)) { + currentId = reader.nextLong(); + } else if (name.equals(ACCESS_DATE)) { + Date date = utcToDate(reader.nextString()); + site.setAccessDate(date); + } else if (name.equals(CLIENT_ID)) { + site.setClientId(reader.nextString()); + } else if (name.equals(CREATION_DATE)) { + Date date = utcToDate(reader.nextString()); + site.setCreationDate(date); + } else if (name.equals(TIMEOUT_DATE)) { + Date date = utcToDate(reader.nextString()); + site.setTimeoutDate(date); + } else if (name.equals(USER_ID)) { + site.setUserId(reader.nextString()); + } else if (name.equals(ALLOWED_SCOPES)) { + Set allowedScopes = readSet(reader); + site.setAllowedScopes(allowedScopes); + } else if (name.equals(APPROVED_ACCESS_TOKENS)) { + tokenIds = readSet(reader); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); + } + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -570,28 +565,28 @@ private void readWhitelistedSites(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (name.equals(ID)) { - currentId = reader.nextLong(); - } else if (name.equals(CLIENT_ID)) { - wlSite.setClientId(reader.nextString()); - } else if (name.equals(CREATOR_USER_ID)) { - wlSite.setCreatorUserId(reader.nextString()); - } else if (name.equals(ALLOWED_SCOPES)) { - Set allowedScopes = readSet(reader); - wlSite.setAllowedScopes(allowedScopes); - } else { + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (name.equals(ID)) { + currentId = reader.nextLong(); + } else if (name.equals(CLIENT_ID)) { + wlSite.setClientId(reader.nextString()); + } else if (name.equals(CREATOR_USER_ID)) { + wlSite.setCreatorUserId(reader.nextString()); + } else if (name.equals(ALLOWED_SCOPES)) { + Set allowedScopes = readSet(reader); + wlSite.setAllowedScopes(allowedScopes); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); + } + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -613,23 +608,23 @@ private void readBlacklistedSites(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (name.equals(ID)) { - reader.skipValue(); - } else if (name.equals(URI)) { - blSite.setUri(reader.nextString()); - } else { + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (name.equals(ID)) { + reader.skipValue(); + } else if (name.equals(URI)) { + blSite.setUri(reader.nextString()); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); + } + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -650,136 +645,136 @@ private void readClients(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals(CLIENT_ID)) { - client.setClientId(reader.nextString()); - } else if (name.equals(RESOURCE_IDS)) { - Set resourceIds = readSet(reader); - client.setResourceIds(resourceIds); - } else if (name.equals(SECRET)) { - client.setClientSecret(reader.nextString()); - } else if (name.equals(SCOPE)) { - Set scope = readSet(reader); - client.setScope(scope); - } else if (name.equals(AUTHORITIES)) { - Set authorityStrs = readSet(reader); - Set authorities = new HashSet(); - for (String s : authorityStrs) { - GrantedAuthority ga = new SimpleGrantedAuthority(s); - authorities.add(ga); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals(CLIENT_ID)) { + client.setClientId(reader.nextString()); + } else if (name.equals(RESOURCE_IDS)) { + Set resourceIds = readSet(reader); + client.setResourceIds(resourceIds); + } else if (name.equals(SECRET)) { + client.setClientSecret(reader.nextString()); + } else if (name.equals(SCOPE)) { + Set scope = readSet(reader); + client.setScope(scope); + } else if (name.equals(AUTHORITIES)) { + Set authorityStrs = readSet(reader); + Set authorities = new HashSet(); + for (String s : authorityStrs) { + GrantedAuthority ga = new SimpleGrantedAuthority(s); + authorities.add(ga); + } + client.setAuthorities(authorities); + } else if (name.equals(ACCESS_TOKEN_VALIDITY_SECONDS)) { + client.setAccessTokenValiditySeconds(reader.nextInt()); + } else if (name.equals(REFRESH_TOKEN_VALIDITY_SECONDS)) { + client.setRefreshTokenValiditySeconds(reader.nextInt()); + } else if (name.equals(REDIRECT_URIS)) { + Set redirectUris = readSet(reader); + client.setRedirectUris(redirectUris); + } else if (name.equals(CLAIMS_REDIRECT_URIS)) { + Set claimsRedirectUris = readSet(reader); + client.setClaimsRedirectUris(claimsRedirectUris); + } else if (name.equals(NAME)) { + client.setClientName(reader.nextString()); + } else if (name.equals(URI)) { + client.setClientUri(reader.nextString()); + } else if (name.equals(LOGO_URI)) { + client.setLogoUri(reader.nextString()); + } else if (name.equals(CONTACTS)) { + Set contacts = readSet(reader); + client.setContacts(contacts); + } else if (name.equals(TOS_URI)) { + client.setTosUri(reader.nextString()); + } else if (name.equals(TOKEN_ENDPOINT_AUTH_METHOD)) { + AuthMethod am = AuthMethod.getByValue(reader.nextString()); + client.setTokenEndpointAuthMethod(am); + } else if (name.equals(GRANT_TYPES)) { + Set grantTypes = readSet(reader); + client.setGrantTypes(grantTypes); + } else if (name.equals(RESPONSE_TYPES)) { + Set responseTypes = readSet(reader); + client.setResponseTypes(responseTypes); + } else if (name.equals(POLICY_URI)) { + client.setPolicyUri(reader.nextString()); + } else if (name.equals(APPLICATION_TYPE)) { + AppType appType = AppType.getByValue(reader.nextString()); + client.setApplicationType(appType); + } else if (name.equals(SECTOR_IDENTIFIER_URI)) { + client.setSectorIdentifierUri(reader.nextString()); + } else if (name.equals(SUBJECT_TYPE)) { + SubjectType st = SubjectType.getByValue(reader.nextString()); + client.setSubjectType(st); + } else if (name.equals(JWKS_URI)) { + client.setJwksUri(reader.nextString()); + } else if (name.equals(JWKS)) { + try { + client.setJwks(JWKSet.parse(reader.nextString())); + } catch (ParseException e) { + logger.error("Couldn't parse JWK Set", e); + } + } else if (name.equals(REQUEST_OBJECT_SIGNING_ALG)) { + JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); + client.setRequestObjectSigningAlg(alg); + } else if (name.equals(USER_INFO_ENCRYPTED_RESPONSE_ALG)) { + JWEAlgorithm alg = JWEAlgorithm.parse(reader.nextString()); + client.setUserInfoEncryptedResponseAlg(alg); + } else if (name.equals(USER_INFO_ENCRYPTED_RESPONSE_ENC)) { + EncryptionMethod alg = EncryptionMethod.parse(reader.nextString()); + client.setUserInfoEncryptedResponseEnc(alg); + } else if (name.equals(USER_INFO_SIGNED_RESPONSE_ALG)) { + JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); + client.setUserInfoSignedResponseAlg(alg); + } else if (name.equals(ID_TOKEN_SIGNED_RESPONSE_ALG)) { + JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); + client.setIdTokenSignedResponseAlg(alg); + } else if (name.equals(ID_TOKEN_ENCRYPTED_RESPONSE_ALG)) { + JWEAlgorithm alg = JWEAlgorithm.parse(reader.nextString()); + client.setIdTokenEncryptedResponseAlg(alg); + } else if (name.equals(ID_TOKEN_ENCRYPTED_RESPONSE_ENC)) { + EncryptionMethod alg = EncryptionMethod.parse(reader.nextString()); + client.setIdTokenEncryptedResponseEnc(alg); + } else if (name.equals(TOKEN_ENDPOINT_AUTH_SIGNING_ALG)) { + JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); + client.setTokenEndpointAuthSigningAlg(alg); + } else if (name.equals(DEFAULT_MAX_AGE)) { + client.setDefaultMaxAge(reader.nextInt()); + } else if (name.equals(REQUIRE_AUTH_TIME)) { + client.setRequireAuthTime(reader.nextBoolean()); + } else if (name.equals(DEFAULT_ACR_VALUES)) { + Set defaultACRvalues = readSet(reader); + client.setDefaultACRvalues(defaultACRvalues); + } else if (name.equals("initiateLoginUri")) { + client.setInitiateLoginUri(reader.nextString()); + } else if (name.equals(POST_LOGOUT_REDIRECT_URI)) { + Set postLogoutUris = readSet(reader); + client.setPostLogoutRedirectUris(postLogoutUris); + } else if (name.equals(REQUEST_URIS)) { + Set requestUris = readSet(reader); + client.setRequestUris(requestUris); + } else if (name.equals(DESCRIPTION)) { + client.setClientDescription(reader.nextString()); + } else if (name.equals(ALLOW_INTROSPECTION)) { + client.setAllowIntrospection(reader.nextBoolean()); + } else if (name.equals(REUSE_REFRESH_TOKEN)) { + client.setReuseRefreshToken(reader.nextBoolean()); + } else if (name.equals(CLEAR_ACCESS_TOKENS_ON_REFRESH)) { + client.setClearAccessTokensOnRefresh(reader.nextBoolean()); + } else if (name.equals(DYNAMICALLY_REGISTERED)) { + client.setDynamicallyRegistered(reader.nextBoolean()); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); } - client.setAuthorities(authorities); - } else if (name.equals(ACCESS_TOKEN_VALIDITY_SECONDS)) { - client.setAccessTokenValiditySeconds(reader.nextInt()); - } else if (name.equals(REFRESH_TOKEN_VALIDITY_SECONDS)) { - client.setRefreshTokenValiditySeconds(reader.nextInt()); - } else if (name.equals(REDIRECT_URIS)) { - Set redirectUris = readSet(reader); - client.setRedirectUris(redirectUris); - } else if (name.equals(CLAIMS_REDIRECT_URIS)) { - Set claimsRedirectUris = readSet(reader); - client.setClaimsRedirectUris(claimsRedirectUris); - } else if (name.equals(NAME)) { - client.setClientName(reader.nextString()); - } else if (name.equals(URI)) { - client.setClientUri(reader.nextString()); - } else if (name.equals(LOGO_URI)) { - client.setLogoUri(reader.nextString()); - } else if (name.equals(CONTACTS)) { - Set contacts = readSet(reader); - client.setContacts(contacts); - } else if (name.equals(TOS_URI)) { - client.setTosUri(reader.nextString()); - } else if (name.equals(TOKEN_ENDPOINT_AUTH_METHOD)) { - AuthMethod am = AuthMethod.getByValue(reader.nextString()); - client.setTokenEndpointAuthMethod(am); - } else if (name.equals(GRANT_TYPES)) { - Set grantTypes = readSet(reader); - client.setGrantTypes(grantTypes); - } else if (name.equals(RESPONSE_TYPES)) { - Set responseTypes = readSet(reader); - client.setResponseTypes(responseTypes); - } else if (name.equals(POLICY_URI)) { - client.setPolicyUri(reader.nextString()); - } else if (name.equals(APPLICATION_TYPE)) { - AppType appType = AppType.getByValue(reader.nextString()); - client.setApplicationType(appType); - } else if (name.equals(SECTOR_IDENTIFIER_URI)) { - client.setSectorIdentifierUri(reader.nextString()); - } else if (name.equals(SUBJECT_TYPE)) { - SubjectType st = SubjectType.getByValue(reader.nextString()); - client.setSubjectType(st); - } else if (name.equals(JWKS_URI)) { - client.setJwksUri(reader.nextString()); - } else if (name.equals(JWKS)) { - try { - client.setJwks(JWKSet.parse(reader.nextString())); - } catch (ParseException e) { - logger.error("Couldn't parse JWK Set", e); - } - } else if (name.equals(REQUEST_OBJECT_SIGNING_ALG)) { - JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); - client.setRequestObjectSigningAlg(alg); - } else if (name.equals(USER_INFO_ENCRYPTED_RESPONSE_ALG)) { - JWEAlgorithm alg = JWEAlgorithm.parse(reader.nextString()); - client.setUserInfoEncryptedResponseAlg(alg); - } else if (name.equals(USER_INFO_ENCRYPTED_RESPONSE_ENC)) { - EncryptionMethod alg = EncryptionMethod.parse(reader.nextString()); - client.setUserInfoEncryptedResponseEnc(alg); - } else if (name.equals(USER_INFO_SIGNED_RESPONSE_ALG)) { - JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); - client.setUserInfoSignedResponseAlg(alg); - } else if (name.equals(ID_TOKEN_SIGNED_RESPONSE_ALG)) { - JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); - client.setIdTokenSignedResponseAlg(alg); - } else if (name.equals(ID_TOKEN_ENCRYPTED_RESPONSE_ALG)) { - JWEAlgorithm alg = JWEAlgorithm.parse(reader.nextString()); - client.setIdTokenEncryptedResponseAlg(alg); - } else if (name.equals(ID_TOKEN_ENCRYPTED_RESPONSE_ENC)) { - EncryptionMethod alg = EncryptionMethod.parse(reader.nextString()); - client.setIdTokenEncryptedResponseEnc(alg); - } else if (name.equals(TOKEN_ENDPOINT_AUTH_SIGNING_ALG)) { - JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); - client.setTokenEndpointAuthSigningAlg(alg); - } else if (name.equals(DEFAULT_MAX_AGE)) { - client.setDefaultMaxAge(reader.nextInt()); - } else if (name.equals(REQUIRE_AUTH_TIME)) { - client.setRequireAuthTime(reader.nextBoolean()); - } else if (name.equals(DEFAULT_ACR_VALUES)) { - Set defaultACRvalues = readSet(reader); - client.setDefaultACRvalues(defaultACRvalues); - } else if (name.equals("initiateLoginUri")) { - client.setInitiateLoginUri(reader.nextString()); - } else if (name.equals(POST_LOGOUT_REDIRECT_URI)) { - Set postLogoutUris = readSet(reader); - client.setPostLogoutRedirectUris(postLogoutUris); - } else if (name.equals(REQUEST_URIS)) { - Set requestUris = readSet(reader); - client.setRequestUris(requestUris); - } else if (name.equals(DESCRIPTION)) { - client.setClientDescription(reader.nextString()); - } else if (name.equals(ALLOW_INTROSPECTION)) { - client.setAllowIntrospection(reader.nextBoolean()); - } else if (name.equals(REUSE_REFRESH_TOKEN)) { - client.setReuseRefreshToken(reader.nextBoolean()); - } else if (name.equals(CLEAR_ACCESS_TOKENS_ON_REFRESH)) { - client.setClearAccessTokensOnRefresh(reader.nextBoolean()); - } else if (name.equals(DYNAMICALLY_REGISTERED)) { - client.setDynamicallyRegistered(reader.nextBoolean()); - } else { + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -803,35 +798,35 @@ private void readSystemScopes(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals(VALUE)) { - scope.setValue(reader.nextString()); - } else if (name.equals(DESCRIPTION)) { - scope.setDescription(reader.nextString()); - } else if (name.equals(RESTRICTED)) { - scope.setRestricted(reader.nextBoolean()); - } else if (name.equals(DEFAULT_SCOPE)) { - scope.setDefaultScope(reader.nextBoolean()); - } else if (name.equals(ICON)) { - scope.setIcon(reader.nextString()); - } else if (name.equals(STRUCTURED)) { - logger.warn("Found a structured scope, ignoring structure"); - } else if (name.equals(STRUCTURED_PARAMETER)) { - logger.warn("Found a structured scope, ignoring structure"); - } else { - logger.debug("found unexpected entry"); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals(VALUE)) { + scope.setValue(reader.nextString()); + } else if (name.equals(DESCRIPTION)) { + scope.setDescription(reader.nextString()); + } else if (name.equals(RESTRICTED)) { + scope.setRestricted(reader.nextBoolean()); + } else if (name.equals(DEFAULT_SCOPE)) { + scope.setDefaultScope(reader.nextBoolean()); + } else if (name.equals(ICON)) { + scope.setIcon(reader.nextString()); + } else if (name.equals(STRUCTURED)) { + logger.warn("Found a structured scope, ignoring structure"); + } else if (name.equals(STRUCTURED_PARAMETER)) { + logger.warn("Found a structured scope, ignoring structure"); + } else { + logger.debug("found unexpected entry"); + reader.skipValue(); + } + break; + default: + logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -898,7 +893,7 @@ private void fixObjectReferences() { token.setApprovedSite(site); tokenRepository.saveAccessToken(token); } - + approvedSiteRepository.save(site); } logger.info("Done fixing object references."); diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_3.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_3.java index caa0110346..582d17f32c 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_3.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_3.java @@ -172,11 +172,11 @@ public class MITREidDataService_1_3 extends MITREidDataServiceSupport implements private SystemScopeRepository sysScopeRepository; @Autowired(required = false) private List extensions = Collections.emptyList(); - + private static final String THIS_VERSION = MITREID_CONNECT_1_3; - - private MITREidDataServiceMaps maps = new MITREidDataServiceMaps(); - + + private MITREidDataServiceMaps maps = new MITREidDataServiceMaps(); + @Override public boolean supportsVersion(String version) { return THIS_VERSION.equals(version); @@ -233,7 +233,7 @@ public void exportData(JsonWriter writer) throws IOException { writer.beginArray(); writeSystemScopes(writer); writer.endArray(); - + for (MITREidDataServiceExtension extension : extensions) { if (extension.supportsVersion(THIS_VERSION)) { extension.exportExtensionData(writer); @@ -574,51 +574,51 @@ public void importData(JsonReader reader) throws IOException { while (reader.hasNext()) { JsonToken tok = reader.peek(); switch (tok) { - case NAME: - String name = reader.nextName(); - // find out which member it is - if (name.equals(CLIENTS)) { - readClients(reader); - } else if (name.equals(GRANTS)) { - readGrants(reader); - } else if (name.equals(WHITELISTEDSITES)) { - readWhitelistedSites(reader); - } else if (name.equals(BLACKLISTEDSITES)) { - readBlacklistedSites(reader); - } else if (name.equals(AUTHENTICATIONHOLDERS)) { - readAuthenticationHolders(reader); - } else if (name.equals(ACCESSTOKENS)) { - readAccessTokens(reader); - } else if (name.equals(REFRESHTOKENS)) { - readRefreshTokens(reader); - } else if (name.equals(SYSTEMSCOPES)) { - readSystemScopes(reader); - } else { - boolean processed = false; - for (MITREidDataServiceExtension extension : extensions) { - if (extension.supportsVersion(THIS_VERSION)) { - processed = extension.importExtensionData(name, reader); - if (processed) { - // if the extension processed data, break out of this inner loop - // (only the first extension to claim an extension point gets it) - break; + case NAME: + String name = reader.nextName(); + // find out which member it is + if (name.equals(CLIENTS)) { + readClients(reader); + } else if (name.equals(GRANTS)) { + readGrants(reader); + } else if (name.equals(WHITELISTEDSITES)) { + readWhitelistedSites(reader); + } else if (name.equals(BLACKLISTEDSITES)) { + readBlacklistedSites(reader); + } else if (name.equals(AUTHENTICATIONHOLDERS)) { + readAuthenticationHolders(reader); + } else if (name.equals(ACCESSTOKENS)) { + readAccessTokens(reader); + } else if (name.equals(REFRESHTOKENS)) { + readRefreshTokens(reader); + } else if (name.equals(SYSTEMSCOPES)) { + readSystemScopes(reader); + } else { + boolean processed = false; + for (MITREidDataServiceExtension extension : extensions) { + if (extension.supportsVersion(THIS_VERSION)) { + processed = extension.importExtensionData(name, reader); + if (processed) { + // if the extension processed data, break out of this inner loop + // (only the first extension to claim an extension point gets it) + break; + } } } + if (!processed) { + // unknown token, skip it + reader.skipValue(); + } } - if (!processed) { - // unknown token, skip it - reader.skipValue(); - } - } - break; - case END_OBJECT: - // the object ended, we're done here - reader.endObject(); - continue; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + break; + case END_OBJECT: + // the object ended, we're done here + reader.endObject(); + continue; + default: + logger.debug("Found unexpected entry"); + reader.skipValue(); + continue; } } fixObjectReferences(); @@ -630,7 +630,7 @@ public void importData(JsonReader reader) throws IOException { } maps.clearAll(); } - + /** * @param reader * @throws IOException @@ -649,37 +649,37 @@ private void readRefreshTokens(JsonReader reader) throws IOException { Long authHolderId = null; while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals(ID)) { - currentId = reader.nextLong(); - } else if (name.equals(EXPIRATION)) { - Date date = utcToDate(reader.nextString()); - token.setExpiration(date); - } else if (name.equals(VALUE)) { - String value = reader.nextString(); - try { - token.setJwt(JWTParser.parse(value)); - } catch (ParseException ex) { - logger.error("Unable to set refresh token value to {}", value, ex); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals(ID)) { + currentId = reader.nextLong(); + } else if (name.equals(EXPIRATION)) { + Date date = utcToDate(reader.nextString()); + token.setExpiration(date); + } else if (name.equals(VALUE)) { + String value = reader.nextString(); + try { + token.setJwt(JWTParser.parse(value)); + } catch (ParseException ex) { + logger.error("Unable to set refresh token value to {}", value, ex); + } + } else if (name.equals(CLIENT_ID)) { + clientId = reader.nextString(); + } else if (name.equals(AUTHENTICATION_HOLDER_ID)) { + authHolderId = reader.nextLong(); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); } - } else if (name.equals(CLIENT_ID)) { - clientId = reader.nextString(); - } else if (name.equals(AUTHENTICATION_HOLDER_ID)) { - authHolderId = reader.nextLong(); - } else { + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -711,45 +711,45 @@ private void readAccessTokens(JsonReader reader) throws IOException { Long refreshTokenId = null; while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals(ID)) { - currentId = reader.nextLong(); - } else if (name.equals(EXPIRATION)) { - Date date = utcToDate(reader.nextString()); - token.setExpiration(date); - } else if (name.equals(VALUE)) { - String value = reader.nextString(); - try { - // all tokens are JWTs - token.setJwt(JWTParser.parse(value)); - } catch (ParseException ex) { - logger.error("Unable to set refresh token value to {}", value, ex); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals(ID)) { + currentId = reader.nextLong(); + } else if (name.equals(EXPIRATION)) { + Date date = utcToDate(reader.nextString()); + token.setExpiration(date); + } else if (name.equals(VALUE)) { + String value = reader.nextString(); + try { + // all tokens are JWTs + token.setJwt(JWTParser.parse(value)); + } catch (ParseException ex) { + logger.error("Unable to set refresh token value to {}", value, ex); + } + } else if (name.equals(CLIENT_ID)) { + clientId = reader.nextString(); + } else if (name.equals(AUTHENTICATION_HOLDER_ID)) { + authHolderId = reader.nextLong(); + } else if (name.equals(REFRESH_TOKEN_ID)) { + refreshTokenId = reader.nextLong(); + } else if (name.equals(SCOPE)) { + Set scope = readSet(reader); + token.setScope(scope); + } else if (name.equals(TYPE)) { + token.setTokenType(reader.nextString()); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); } - } else if (name.equals(CLIENT_ID)) { - clientId = reader.nextString(); - } else if (name.equals(AUTHENTICATION_HOLDER_ID)) { - authHolderId = reader.nextLong(); - } else if (name.equals(REFRESH_TOKEN_ID)) { - refreshTokenId = reader.nextLong(); - } else if (name.equals(SCOPE)) { - Set scope = readSet(reader); - token.setScope(scope); - } else if (name.equals(TYPE)) { - token.setTokenType(reader.nextString()); - } else { + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -777,49 +777,49 @@ private void readAuthenticationHolders(JsonReader reader) throws IOException { Long currentId = null; while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals(ID)) { - currentId = reader.nextLong(); - } else if (name.equals(REQUEST_PARAMETERS)) { - ahe.setRequestParameters(readMap(reader)); - } else if (name.equals(CLIENT_ID)) { - ahe.setClientId(reader.nextString()); - } else if (name.equals(SCOPE)) { - ahe.setScope(readSet(reader)); - } else if (name.equals(RESOURCE_IDS)) { - ahe.setResourceIds(readSet(reader)); - } else if (name.equals(AUTHORITIES)) { - Set authorityStrs = readSet(reader); - Set authorities = new HashSet(); - for (String s : authorityStrs) { - GrantedAuthority ga = new SimpleGrantedAuthority(s); - authorities.add(ga); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals(ID)) { + currentId = reader.nextLong(); + } else if (name.equals(REQUEST_PARAMETERS)) { + ahe.setRequestParameters(readMap(reader)); + } else if (name.equals(CLIENT_ID)) { + ahe.setClientId(reader.nextString()); + } else if (name.equals(SCOPE)) { + ahe.setScope(readSet(reader)); + } else if (name.equals(RESOURCE_IDS)) { + ahe.setResourceIds(readSet(reader)); + } else if (name.equals(AUTHORITIES)) { + Set authorityStrs = readSet(reader); + Set authorities = new HashSet(); + for (String s : authorityStrs) { + GrantedAuthority ga = new SimpleGrantedAuthority(s); + authorities.add(ga); + } + ahe.setAuthorities(authorities); + } else if (name.equals(APPROVED)) { + ahe.setApproved(reader.nextBoolean()); + } else if (name.equals(REDIRECT_URI)) { + ahe.setRedirectUri(reader.nextString()); + } else if (name.equals(RESPONSE_TYPES)) { + ahe.setResponseTypes(readSet(reader)); + } else if (name.equals(EXTENSIONS)) { + ahe.setExtensions(readMap(reader)); + } else if (name.equals(SAVED_USER_AUTHENTICATION)) { + ahe.setUserAuth(readSavedUserAuthentication(reader)); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); } - ahe.setAuthorities(authorities); - } else if (name.equals(APPROVED)) { - ahe.setApproved(reader.nextBoolean()); - } else if (name.equals(REDIRECT_URI)) { - ahe.setRedirectUri(reader.nextString()); - } else if (name.equals(RESPONSE_TYPES)) { - ahe.setResponseTypes(readSet(reader)); - } else if (name.equals(EXTENSIONS)) { - ahe.setExtensions(readMap(reader)); - } else if (name.equals(SAVED_USER_AUTHENTICATION)) { - ahe.setUserAuth(readSavedUserAuthentication(reader)); - } else { + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -842,35 +842,35 @@ private SavedUserAuthentication readSavedUserAuthentication(JsonReader reader) t while (reader.hasNext()) { switch(reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals(NAME)) { - savedUserAuth.setName(reader.nextString()); - } else if (name.equals(SOURCE_CLASS)) { - savedUserAuth.setSourceClass(reader.nextString()); - } else if (name.equals(AUTHENTICATED)) { - savedUserAuth.setAuthenticated(reader.nextBoolean()); - } else if (name.equals(AUTHORITIES)) { - Set authorityStrs = readSet(reader); - Set authorities = new HashSet(); - for (String s : authorityStrs) { - GrantedAuthority ga = new SimpleGrantedAuthority(s); - authorities.add(ga); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals(NAME)) { + savedUserAuth.setName(reader.nextString()); + } else if (name.equals(SOURCE_CLASS)) { + savedUserAuth.setSourceClass(reader.nextString()); + } else if (name.equals(AUTHENTICATED)) { + savedUserAuth.setAuthenticated(reader.nextBoolean()); + } else if (name.equals(AUTHORITIES)) { + Set authorityStrs = readSet(reader); + Set authorities = new HashSet(); + for (String s : authorityStrs) { + GrantedAuthority ga = new SimpleGrantedAuthority(s); + authorities.add(ga); + } + savedUserAuth.setAuthorities(authorities); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); } - savedUserAuth.setAuthorities(authorities); - } else { + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } @@ -891,41 +891,41 @@ private void readGrants(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals(ID)) { - currentId = reader.nextLong(); - } else if (name.equals(ACCESS_DATE)) { - Date date = utcToDate(reader.nextString()); - site.setAccessDate(date); - } else if (name.equals(CLIENT_ID)) { - site.setClientId(reader.nextString()); - } else if (name.equals(CREATION_DATE)) { - Date date = utcToDate(reader.nextString()); - site.setCreationDate(date); - } else if (name.equals(TIMEOUT_DATE)) { - Date date = utcToDate(reader.nextString()); - site.setTimeoutDate(date); - } else if (name.equals(USER_ID)) { - site.setUserId(reader.nextString()); - } else if (name.equals(ALLOWED_SCOPES)) { - Set allowedScopes = readSet(reader); - site.setAllowedScopes(allowedScopes); - } else if (name.equals(APPROVED_ACCESS_TOKENS)) { - tokenIds = readSet(reader); - } else { + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals(ID)) { + currentId = reader.nextLong(); + } else if (name.equals(ACCESS_DATE)) { + Date date = utcToDate(reader.nextString()); + site.setAccessDate(date); + } else if (name.equals(CLIENT_ID)) { + site.setClientId(reader.nextString()); + } else if (name.equals(CREATION_DATE)) { + Date date = utcToDate(reader.nextString()); + site.setCreationDate(date); + } else if (name.equals(TIMEOUT_DATE)) { + Date date = utcToDate(reader.nextString()); + site.setTimeoutDate(date); + } else if (name.equals(USER_ID)) { + site.setUserId(reader.nextString()); + } else if (name.equals(ALLOWED_SCOPES)) { + Set allowedScopes = readSet(reader); + site.setAllowedScopes(allowedScopes); + } else if (name.equals(APPROVED_ACCESS_TOKENS)) { + tokenIds = readSet(reader); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); + } + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -939,7 +939,7 @@ private void readGrants(JsonReader reader) throws IOException { reader.endArray(); logger.info("Done reading grants"); } - + /** * @param reader * @throws IOException @@ -952,28 +952,28 @@ private void readWhitelistedSites(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (name.equals(ID)) { - currentId = reader.nextLong(); - } else if (name.equals(CLIENT_ID)) { - wlSite.setClientId(reader.nextString()); - } else if (name.equals(CREATOR_USER_ID)) { - wlSite.setCreatorUserId(reader.nextString()); - } else if (name.equals(ALLOWED_SCOPES)) { - Set allowedScopes = readSet(reader); - wlSite.setAllowedScopes(allowedScopes); - } else { + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (name.equals(ID)) { + currentId = reader.nextLong(); + } else if (name.equals(CLIENT_ID)) { + wlSite.setClientId(reader.nextString()); + } else if (name.equals(CREATOR_USER_ID)) { + wlSite.setCreatorUserId(reader.nextString()); + } else if (name.equals(ALLOWED_SCOPES)) { + Set allowedScopes = readSet(reader); + wlSite.setAllowedScopes(allowedScopes); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); + } + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -995,23 +995,23 @@ private void readBlacklistedSites(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (name.equals(ID)) { - reader.skipValue(); - } else if (name.equals(URI)) { - blSite.setUri(reader.nextString()); - } else { + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (name.equals(ID)) { + reader.skipValue(); + } else if (name.equals(URI)) { + blSite.setUri(reader.nextString()); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); + } + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -1032,152 +1032,152 @@ private void readClients(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals(CLIENT_ID)) { - client.setClientId(reader.nextString()); - } else if (name.equals(RESOURCE_IDS)) { - Set resourceIds = readSet(reader); - client.setResourceIds(resourceIds); - } else if (name.equals(SECRET)) { - client.setClientSecret(reader.nextString()); - } else if (name.equals(SCOPE)) { - Set scope = readSet(reader); - client.setScope(scope); - } else if (name.equals(AUTHORITIES)) { - Set authorityStrs = readSet(reader); - Set authorities = new HashSet(); - for (String s : authorityStrs) { - GrantedAuthority ga = new SimpleGrantedAuthority(s); - authorities.add(ga); - } - client.setAuthorities(authorities); - } else if (name.equals(ACCESS_TOKEN_VALIDITY_SECONDS)) { - client.setAccessTokenValiditySeconds(reader.nextInt()); - } else if (name.equals(REFRESH_TOKEN_VALIDITY_SECONDS)) { - client.setRefreshTokenValiditySeconds(reader.nextInt()); - } else if (name.equals(ID_TOKEN_VALIDITY_SECONDS)) { - client.setIdTokenValiditySeconds(reader.nextInt()); - } else if (name.equals(DEVICE_CODE_VALIDITY_SECONDS)) { - client.setDeviceCodeValiditySeconds(reader.nextInt()); - } else if (name.equals(REDIRECT_URIS)) { - Set redirectUris = readSet(reader); - client.setRedirectUris(redirectUris); - } else if (name.equals(CLAIMS_REDIRECT_URIS)) { - Set claimsRedirectUris = readSet(reader); - client.setClaimsRedirectUris(claimsRedirectUris); - } else if (name.equals(NAME)) { - client.setClientName(reader.nextString()); - } else if (name.equals(URI)) { - client.setClientUri(reader.nextString()); - } else if (name.equals(LOGO_URI)) { - client.setLogoUri(reader.nextString()); - } else if (name.equals(CONTACTS)) { - Set contacts = readSet(reader); - client.setContacts(contacts); - } else if (name.equals(TOS_URI)) { - client.setTosUri(reader.nextString()); - } else if (name.equals(TOKEN_ENDPOINT_AUTH_METHOD)) { - AuthMethod am = AuthMethod.getByValue(reader.nextString()); - client.setTokenEndpointAuthMethod(am); - } else if (name.equals(GRANT_TYPES)) { - Set grantTypes = readSet(reader); - client.setGrantTypes(grantTypes); - } else if (name.equals(RESPONSE_TYPES)) { - Set responseTypes = readSet(reader); - client.setResponseTypes(responseTypes); - } else if (name.equals(POLICY_URI)) { - client.setPolicyUri(reader.nextString()); - } else if (name.equals(APPLICATION_TYPE)) { - AppType appType = AppType.getByValue(reader.nextString()); - client.setApplicationType(appType); - } else if (name.equals(SECTOR_IDENTIFIER_URI)) { - client.setSectorIdentifierUri(reader.nextString()); - } else if (name.equals(SUBJECT_TYPE)) { - SubjectType st = SubjectType.getByValue(reader.nextString()); - client.setSubjectType(st); - } else if (name.equals(JWKS_URI)) { - client.setJwksUri(reader.nextString()); - } else if (name.equals(JWKS)) { - try { - client.setJwks(JWKSet.parse(reader.nextString())); - } catch (ParseException e) { - logger.error("Couldn't parse JWK Set", e); - } - } else if (name.equals(REQUEST_OBJECT_SIGNING_ALG)) { - JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); - client.setRequestObjectSigningAlg(alg); - } else if (name.equals(USER_INFO_ENCRYPTED_RESPONSE_ALG)) { - JWEAlgorithm alg = JWEAlgorithm.parse(reader.nextString()); - client.setUserInfoEncryptedResponseAlg(alg); - } else if (name.equals(USER_INFO_ENCRYPTED_RESPONSE_ENC)) { - EncryptionMethod alg = EncryptionMethod.parse(reader.nextString()); - client.setUserInfoEncryptedResponseEnc(alg); - } else if (name.equals(USER_INFO_SIGNED_RESPONSE_ALG)) { - JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); - client.setUserInfoSignedResponseAlg(alg); - } else if (name.equals(ID_TOKEN_SIGNED_RESPONSE_ALG)) { - JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); - client.setIdTokenSignedResponseAlg(alg); - } else if (name.equals(ID_TOKEN_ENCRYPTED_RESPONSE_ALG)) { - JWEAlgorithm alg = JWEAlgorithm.parse(reader.nextString()); - client.setIdTokenEncryptedResponseAlg(alg); - } else if (name.equals(ID_TOKEN_ENCRYPTED_RESPONSE_ENC)) { - EncryptionMethod alg = EncryptionMethod.parse(reader.nextString()); - client.setIdTokenEncryptedResponseEnc(alg); - } else if (name.equals(TOKEN_ENDPOINT_AUTH_SIGNING_ALG)) { - JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); - client.setTokenEndpointAuthSigningAlg(alg); - } else if (name.equals(DEFAULT_MAX_AGE)) { - client.setDefaultMaxAge(reader.nextInt()); - } else if (name.equals(REQUIRE_AUTH_TIME)) { - client.setRequireAuthTime(reader.nextBoolean()); - } else if (name.equals(DEFAULT_ACR_VALUES)) { - Set defaultACRvalues = readSet(reader); - client.setDefaultACRvalues(defaultACRvalues); - } else if (name.equals("initiateLoginUri")) { - client.setInitiateLoginUri(reader.nextString()); - } else if (name.equals(POST_LOGOUT_REDIRECT_URI)) { - Set postLogoutUris = readSet(reader); - client.setPostLogoutRedirectUris(postLogoutUris); - } else if (name.equals(REQUEST_URIS)) { - Set requestUris = readSet(reader); - client.setRequestUris(requestUris); - } else if (name.equals(DESCRIPTION)) { - client.setClientDescription(reader.nextString()); - } else if (name.equals(ALLOW_INTROSPECTION)) { - client.setAllowIntrospection(reader.nextBoolean()); - } else if (name.equals(REUSE_REFRESH_TOKEN)) { - client.setReuseRefreshToken(reader.nextBoolean()); - } else if (name.equals(CLEAR_ACCESS_TOKENS_ON_REFRESH)) { - client.setClearAccessTokensOnRefresh(reader.nextBoolean()); - } else if (name.equals(DYNAMICALLY_REGISTERED)) { - client.setDynamicallyRegistered(reader.nextBoolean()); - } else if (name.equals(CODE_CHALLENGE_METHOD)) { - client.setCodeChallengeMethod(PKCEAlgorithm.parse(reader.nextString())); - } else if (name.equals(SOFTWARE_ID)) { - client.setSoftwareId(reader.nextString()); - } else if (name.equals(SOFTWARE_VERSION)) { - client.setSoftwareVersion(reader.nextString()); - } else if (name.equals(SOFTWARE_STATEMENT)) { - try { - client.setSoftwareStatement(JWTParser.parse(reader.nextString())); - } catch (ParseException e) { - logger.error("Couldn't parse software statement", e); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals(CLIENT_ID)) { + client.setClientId(reader.nextString()); + } else if (name.equals(RESOURCE_IDS)) { + Set resourceIds = readSet(reader); + client.setResourceIds(resourceIds); + } else if (name.equals(SECRET)) { + client.setClientSecret(reader.nextString()); + } else if (name.equals(SCOPE)) { + Set scope = readSet(reader); + client.setScope(scope); + } else if (name.equals(AUTHORITIES)) { + Set authorityStrs = readSet(reader); + Set authorities = new HashSet(); + for (String s : authorityStrs) { + GrantedAuthority ga = new SimpleGrantedAuthority(s); + authorities.add(ga); + } + client.setAuthorities(authorities); + } else if (name.equals(ACCESS_TOKEN_VALIDITY_SECONDS)) { + client.setAccessTokenValiditySeconds(reader.nextInt()); + } else if (name.equals(REFRESH_TOKEN_VALIDITY_SECONDS)) { + client.setRefreshTokenValiditySeconds(reader.nextInt()); + } else if (name.equals(ID_TOKEN_VALIDITY_SECONDS)) { + client.setIdTokenValiditySeconds(reader.nextInt()); + } else if (name.equals(DEVICE_CODE_VALIDITY_SECONDS)) { + client.setDeviceCodeValiditySeconds(reader.nextInt()); + } else if (name.equals(REDIRECT_URIS)) { + Set redirectUris = readSet(reader); + client.setRedirectUris(redirectUris); + } else if (name.equals(CLAIMS_REDIRECT_URIS)) { + Set claimsRedirectUris = readSet(reader); + client.setClaimsRedirectUris(claimsRedirectUris); + } else if (name.equals(NAME)) { + client.setClientName(reader.nextString()); + } else if (name.equals(URI)) { + client.setClientUri(reader.nextString()); + } else if (name.equals(LOGO_URI)) { + client.setLogoUri(reader.nextString()); + } else if (name.equals(CONTACTS)) { + Set contacts = readSet(reader); + client.setContacts(contacts); + } else if (name.equals(TOS_URI)) { + client.setTosUri(reader.nextString()); + } else if (name.equals(TOKEN_ENDPOINT_AUTH_METHOD)) { + AuthMethod am = AuthMethod.getByValue(reader.nextString()); + client.setTokenEndpointAuthMethod(am); + } else if (name.equals(GRANT_TYPES)) { + Set grantTypes = readSet(reader); + client.setGrantTypes(grantTypes); + } else if (name.equals(RESPONSE_TYPES)) { + Set responseTypes = readSet(reader); + client.setResponseTypes(responseTypes); + } else if (name.equals(POLICY_URI)) { + client.setPolicyUri(reader.nextString()); + } else if (name.equals(APPLICATION_TYPE)) { + AppType appType = AppType.getByValue(reader.nextString()); + client.setApplicationType(appType); + } else if (name.equals(SECTOR_IDENTIFIER_URI)) { + client.setSectorIdentifierUri(reader.nextString()); + } else if (name.equals(SUBJECT_TYPE)) { + SubjectType st = SubjectType.getByValue(reader.nextString()); + client.setSubjectType(st); + } else if (name.equals(JWKS_URI)) { + client.setJwksUri(reader.nextString()); + } else if (name.equals(JWKS)) { + try { + client.setJwks(JWKSet.parse(reader.nextString())); + } catch (ParseException e) { + logger.error("Couldn't parse JWK Set", e); + } + } else if (name.equals(REQUEST_OBJECT_SIGNING_ALG)) { + JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); + client.setRequestObjectSigningAlg(alg); + } else if (name.equals(USER_INFO_ENCRYPTED_RESPONSE_ALG)) { + JWEAlgorithm alg = JWEAlgorithm.parse(reader.nextString()); + client.setUserInfoEncryptedResponseAlg(alg); + } else if (name.equals(USER_INFO_ENCRYPTED_RESPONSE_ENC)) { + EncryptionMethod alg = EncryptionMethod.parse(reader.nextString()); + client.setUserInfoEncryptedResponseEnc(alg); + } else if (name.equals(USER_INFO_SIGNED_RESPONSE_ALG)) { + JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); + client.setUserInfoSignedResponseAlg(alg); + } else if (name.equals(ID_TOKEN_SIGNED_RESPONSE_ALG)) { + JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); + client.setIdTokenSignedResponseAlg(alg); + } else if (name.equals(ID_TOKEN_ENCRYPTED_RESPONSE_ALG)) { + JWEAlgorithm alg = JWEAlgorithm.parse(reader.nextString()); + client.setIdTokenEncryptedResponseAlg(alg); + } else if (name.equals(ID_TOKEN_ENCRYPTED_RESPONSE_ENC)) { + EncryptionMethod alg = EncryptionMethod.parse(reader.nextString()); + client.setIdTokenEncryptedResponseEnc(alg); + } else if (name.equals(TOKEN_ENDPOINT_AUTH_SIGNING_ALG)) { + JWSAlgorithm alg = JWSAlgorithm.parse(reader.nextString()); + client.setTokenEndpointAuthSigningAlg(alg); + } else if (name.equals(DEFAULT_MAX_AGE)) { + client.setDefaultMaxAge(reader.nextInt()); + } else if (name.equals(REQUIRE_AUTH_TIME)) { + client.setRequireAuthTime(reader.nextBoolean()); + } else if (name.equals(DEFAULT_ACR_VALUES)) { + Set defaultACRvalues = readSet(reader); + client.setDefaultACRvalues(defaultACRvalues); + } else if (name.equals("initiateLoginUri")) { + client.setInitiateLoginUri(reader.nextString()); + } else if (name.equals(POST_LOGOUT_REDIRECT_URI)) { + Set postLogoutUris = readSet(reader); + client.setPostLogoutRedirectUris(postLogoutUris); + } else if (name.equals(REQUEST_URIS)) { + Set requestUris = readSet(reader); + client.setRequestUris(requestUris); + } else if (name.equals(DESCRIPTION)) { + client.setClientDescription(reader.nextString()); + } else if (name.equals(ALLOW_INTROSPECTION)) { + client.setAllowIntrospection(reader.nextBoolean()); + } else if (name.equals(REUSE_REFRESH_TOKEN)) { + client.setReuseRefreshToken(reader.nextBoolean()); + } else if (name.equals(CLEAR_ACCESS_TOKENS_ON_REFRESH)) { + client.setClearAccessTokensOnRefresh(reader.nextBoolean()); + } else if (name.equals(DYNAMICALLY_REGISTERED)) { + client.setDynamicallyRegistered(reader.nextBoolean()); + } else if (name.equals(CODE_CHALLENGE_METHOD)) { + client.setCodeChallengeMethod(PKCEAlgorithm.parse(reader.nextString())); + } else if (name.equals(SOFTWARE_ID)) { + client.setSoftwareId(reader.nextString()); + } else if (name.equals(SOFTWARE_VERSION)) { + client.setSoftwareVersion(reader.nextString()); + } else if (name.equals(SOFTWARE_STATEMENT)) { + try { + client.setSoftwareStatement(JWTParser.parse(reader.nextString())); + } catch (ParseException e) { + logger.error("Couldn't parse software statement", e); + } + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); } - } else { + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -1201,31 +1201,31 @@ private void readSystemScopes(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals(VALUE)) { - scope.setValue(reader.nextString()); - } else if (name.equals(DESCRIPTION)) { - scope.setDescription(reader.nextString()); - } else if (name.equals(RESTRICTED)) { - scope.setRestricted(reader.nextBoolean()); - } else if (name.equals(DEFAULT_SCOPE)) { - scope.setDefaultScope(reader.nextBoolean()); - } else if (name.equals(ICON)) { - scope.setIcon(reader.nextString()); - } else { - logger.debug("found unexpected entry"); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals(VALUE)) { + scope.setValue(reader.nextString()); + } else if (name.equals(DESCRIPTION)) { + scope.setDescription(reader.nextString()); + } else if (name.equals(RESTRICTED)) { + scope.setRestricted(reader.nextBoolean()); + } else if (name.equals(DEFAULT_SCOPE)) { + scope.setDefaultScope(reader.nextBoolean()); + } else if (name.equals(ICON)) { + scope.setIcon(reader.nextString()); + } else { + logger.debug("found unexpected entry"); + reader.skipValue(); + } + break; + default: + logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -1292,7 +1292,7 @@ private void fixObjectReferences() { token.setApprovedSite(site); tokenRepository.saveAccessToken(token); } - + approvedSiteRepository.save(site); } /* @@ -1304,7 +1304,7 @@ private void fixObjectReferences() { refreshTokenOldToNewIdMap.clear(); accessTokenOldToNewIdMap.clear(); grantOldToNewIdMap.clear(); - */ + */ logger.info("Done fixing object references."); } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MatchLoginHintsAgainstUsers.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MatchLoginHintsAgainstUsers.java index a6db39604b..d8c30f06a4 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MatchLoginHintsAgainstUsers.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MatchLoginHintsAgainstUsers.java @@ -33,7 +33,7 @@ public class MatchLoginHintsAgainstUsers implements LoginHintExtracter { @Autowired private UserInfoService userInfoService; - + /* (non-Javadoc) * @see org.mitre.openid.connect.service.LoginHintTester#useHint(java.lang.String) */ diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/PassAllLoginHints.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/PassAllLoginHints.java index c3b9d6bcda..97b2181751 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/PassAllLoginHints.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/PassAllLoginHints.java @@ -21,7 +21,7 @@ /** * Sends all login hints through to the login page regardless of setup. - * + * * @author jricher * */ diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/RemoveLoginHintsWithHTTP.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/RemoveLoginHintsWithHTTP.java index 2465ce7992..4c036ba2a4 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/RemoveLoginHintsWithHTTP.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/RemoveLoginHintsWithHTTP.java @@ -23,7 +23,7 @@ /** * Passes login hints that don't start with "http" - * + * * @author jricher * */ diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/UUIDPairwiseIdentiferService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/UUIDPairwiseIdentiferService.java index 79baf4c597..088fedb887 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/UUIDPairwiseIdentiferService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/UUIDPairwiseIdentiferService.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.service.impl; diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/ConnectTokenEnhancer.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/ConnectTokenEnhancer.java index 6c7a88acfd..44f9fd947d 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/ConnectTokenEnhancer.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/ConnectTokenEnhancer.java @@ -20,15 +20,12 @@ import java.util.UUID; import org.mitre.jwt.signer.service.JWTSigningAndValidationService; -import org.mitre.jwt.signer.service.impl.JWKSetCacheService; -import org.mitre.jwt.signer.service.impl.SymmetricKeyJWTValidatorCacheService; import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.model.OAuth2AccessTokenEntity; import org.mitre.oauth2.service.ClientDetailsEntityService; import org.mitre.oauth2.service.SystemScopeService; import org.mitre.openid.connect.config.ConfigurationPropertiesBean; import org.mitre.openid.connect.model.UserInfo; -import org.mitre.openid.connect.service.ApprovedSiteService; import org.mitre.openid.connect.service.OIDCTokenService; import org.mitre.openid.connect.service.UserInfoService; import org.slf4j.Logger; @@ -66,22 +63,12 @@ public class ConnectTokenEnhancer implements TokenEnhancer { @Autowired private ClientDetailsEntityService clientService; - @Autowired - private ApprovedSiteService approvedSiteService; - @Autowired private UserInfoService userInfoService; @Autowired private OIDCTokenService connectTokenService; - @Autowired - private JWKSetCacheService encryptors; - - @Autowired - private SymmetricKeyJWTValidatorCacheService symmetricCacheService; - - @Override public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { @@ -98,12 +85,12 @@ public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentica .expirationTime(token.getExpiration()) .subject(authentication.getName()) .jwtID(UUID.randomUUID().toString()); // set a random NONCE in the middle of it - + String audience = (String) authentication.getOAuth2Request().getExtensions().get("aud"); if (!Strings.isNullOrEmpty(audience)) { builder.audience(Lists.newArrayList(audience)); } - + JWTClaimsSet claims = builder.build(); JWSAlgorithm signingAlg = jwtService.getDefaultSigningAlgorithm(); @@ -121,7 +108,7 @@ public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentica * may or may not include the scope parameter. As long as the AuthorizationRequest * has the proper scope, we can consider this a valid OpenID Connect request. Otherwise, * we consider it to be a vanilla OAuth2 request. - * + * * Also, there must be a user authentication involved in the request for it to be considered * OIDC and not OAuth, so we check for that as well. */ @@ -171,6 +158,6 @@ public ClientDetailsEntityService getClientService() { public void setClientService(ClientDetailsEntityService clientService) { this.clientService = clientService; } - + } \ No newline at end of file diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/TofuUserApprovalHandler.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/TofuUserApprovalHandler.java index 5e2aadfbc1..316204a832 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/TofuUserApprovalHandler.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/TofuUserApprovalHandler.java @@ -31,7 +31,6 @@ import javax.servlet.http.HttpSession; -import org.mitre.oauth2.model.SystemScope; import org.mitre.oauth2.service.SystemScopeService; import org.mitre.openid.connect.model.ApprovedSite; import org.mitre.openid.connect.model.WhitelistedSite; @@ -55,13 +54,13 @@ /** * Custom User Approval Handler implementation which uses a concept of a whitelist, * blacklist, and greylist. - * + * * Blacklisted sites will be caught and handled before this * point. - * + * * Whitelisted sites will be automatically approved, and an ApprovedSite entry will * be created for the site the first time a given user access it. - * + * * All other sites fall into the greylist - the user will be presented with the user * approval page upon their first visit * @author aanganes @@ -85,12 +84,12 @@ public class TofuUserApprovalHandler implements UserApprovalHandler { /** * Check if the user has already stored a positive approval decision for this site; or if the * site is whitelisted, approve it automatically. - * + * * Otherwise, return false so that the user will see the approval page and can make their own decision. - * + * * @param authorizationRequest the incoming authorization request * @param userAuthentication the Principal representing the currently-logged-in user - * + * * @return true if the site is approved, false otherwise */ @Override @@ -111,12 +110,12 @@ public boolean isApproved(AuthorizationRequest authorizationRequest, Authenticat /** * Check if the user has already stored a positive approval decision for this site; or if the * site is whitelisted, approve it automatically. - * + * * Otherwise the user will be directed to the approval page and can make their own decision. - * + * * @param authorizationRequest the incoming authorization request * @param userAuthentication the Principal representing the currently-logged-in user - * + * * @return the updated AuthorizationRequest */ @Override @@ -241,7 +240,7 @@ public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizati /** * Get the auth time out of the current session and add it to the * auth request in the extensions map. - * + * * @param authorizationRequest */ private void setAuthTime(AuthorizationRequest authorizationRequest) { diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/util/IdTokenHashUtils.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/util/IdTokenHashUtils.java index 43b7e0ed83..0f40b69d65 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/util/IdTokenHashUtils.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/util/IdTokenHashUtils.java @@ -31,9 +31,9 @@ /** * Utility class for generating hashes for access tokens and authorization codes * to be included in an ID Token. - * + * * @author Amanda Anganes - * + * */ public class IdTokenHashUtils { @@ -44,7 +44,7 @@ public class IdTokenHashUtils { /** * Compute the SHA hash of an authorization code - * + * * @param signingAlg * @param code * @return @@ -55,7 +55,7 @@ public static Base64URL getCodeHash(JWSAlgorithm signingAlg, String code) { /** * Compute the SHA hash of a token - * + * * @param signingAlg * @param token * @return diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/AbstractClientEntityView.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/AbstractClientEntityView.java index 5b3229c429..465e424654 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/AbstractClientEntityView.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/AbstractClientEntityView.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.view; @@ -37,15 +37,11 @@ import com.google.gson.ExclusionStrategy; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; import com.google.gson.JsonParser; import com.google.gson.JsonPrimitive; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; -import com.nimbusds.jose.Algorithm; import com.nimbusds.jose.EncryptionMethod; import com.nimbusds.jose.JWEAlgorithm; import com.nimbusds.jose.JWSAlgorithm; @@ -53,12 +49,12 @@ import com.nimbusds.jwt.JWT; /** - * + * * Abstract superclass for client entity view, used with the ClientApi. - * + * * @see ClientEntityViewForUsers * @see ClientEntityViewForAdmins - * + * * @author jricher * */ @@ -71,70 +67,71 @@ public abstract class AbstractClientEntityView extends AbstractView { private JsonParser parser = new JsonParser(); private Gson gson = new GsonBuilder() - .setExclusionStrategies(getExclusionStrategy()) - .registerTypeAdapter(JWSAlgorithm.class, new JsonSerializer() { - @Override - public JsonElement serialize(JWSAlgorithm src, Type typeOfSrc, JsonSerializationContext context) { - if (src != null) { - return new JsonPrimitive(src.getName()); - } else { - return null; - } - } - }) - .registerTypeAdapter(JWEAlgorithm.class, new JsonSerializer() { - @Override - public JsonElement serialize(JWEAlgorithm src, Type typeOfSrc, JsonSerializationContext context) { - if (src != null) { - return new JsonPrimitive(src.getName()); - } else { - return null; - } - } - }) - .registerTypeAdapter(EncryptionMethod.class, new JsonSerializer() { - @Override - public JsonElement serialize(EncryptionMethod src, Type typeOfSrc, JsonSerializationContext context) { - if (src != null) { - return new JsonPrimitive(src.getName()); - } else { - return null; - } - } - }) - .registerTypeAdapter(JWKSet.class, new JsonSerializer() { - @Override - public JsonElement serialize(JWKSet src, Type typeOfSrc, JsonSerializationContext context) { - if (src != null) { - return parser.parse(src.toString()); - } else { - return null; - } - } - }) - .registerTypeAdapter(JWT.class, new JsonSerializer() { - @Override - public JsonElement serialize(JWT src, Type typeOfSrc, JsonSerializationContext context) { - if (src != null) { - return new JsonPrimitive(src.serialize()); - } else { - return null; - } - } - - }) - .registerTypeAdapter(PKCEAlgorithm.class, new JsonSerializer() { - public JsonPrimitive serialize(PKCEAlgorithm src, Type typeOfSrc, JsonSerializationContext context) { - if (src != null) { - return new JsonPrimitive(src.getName()); - } else { - return null; - } - } - }) - .serializeNulls() - .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") - .create(); + .setExclusionStrategies(getExclusionStrategy()) + .registerTypeAdapter(JWSAlgorithm.class, new JsonSerializer() { + @Override + public JsonElement serialize(JWSAlgorithm src, Type typeOfSrc, JsonSerializationContext context) { + if (src != null) { + return new JsonPrimitive(src.getName()); + } else { + return null; + } + } + }) + .registerTypeAdapter(JWEAlgorithm.class, new JsonSerializer() { + @Override + public JsonElement serialize(JWEAlgorithm src, Type typeOfSrc, JsonSerializationContext context) { + if (src != null) { + return new JsonPrimitive(src.getName()); + } else { + return null; + } + } + }) + .registerTypeAdapter(EncryptionMethod.class, new JsonSerializer() { + @Override + public JsonElement serialize(EncryptionMethod src, Type typeOfSrc, JsonSerializationContext context) { + if (src != null) { + return new JsonPrimitive(src.getName()); + } else { + return null; + } + } + }) + .registerTypeAdapter(JWKSet.class, new JsonSerializer() { + @Override + public JsonElement serialize(JWKSet src, Type typeOfSrc, JsonSerializationContext context) { + if (src != null) { + return parser.parse(src.toString()); + } else { + return null; + } + } + }) + .registerTypeAdapter(JWT.class, new JsonSerializer() { + @Override + public JsonElement serialize(JWT src, Type typeOfSrc, JsonSerializationContext context) { + if (src != null) { + return new JsonPrimitive(src.serialize()); + } else { + return null; + } + } + + }) + .registerTypeAdapter(PKCEAlgorithm.class, new JsonSerializer() { + @Override + public JsonPrimitive serialize(PKCEAlgorithm src, Type typeOfSrc, JsonSerializationContext context) { + if (src != null) { + return new JsonPrimitive(src.getName()); + } else { + return null; + } + } + }) + .serializeNulls() + .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") + .create(); /** diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientEntityViewForAdmins.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientEntityViewForAdmins.java index 88ee0c60af..98f9d93833 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientEntityViewForAdmins.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientEntityViewForAdmins.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.view; @@ -29,9 +29,9 @@ import com.google.gson.FieldAttributes; /** - * + * * View bean for full view of client entity, for admins. - * + * * @see ClientEntityViewForUsers * @author jricher * diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientEntityViewForUsers.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientEntityViewForUsers.java index 4aaf55e8df..251fda1765 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientEntityViewForUsers.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientEntityViewForUsers.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.view; @@ -29,9 +29,9 @@ import com.google.gson.FieldAttributes; /** - * + * * View bean for field-limited view of client entity, for regular users. - * + * * @see AbstractClientEntityView * @see ClientEntityViewForAdmins * @author jricher diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientInformationResponseView.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientInformationResponseView.java index 1ab7c8452d..bce6a5532e 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientInformationResponseView.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientInformationResponseView.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.view; @@ -40,10 +40,10 @@ import com.google.gson.JsonObject; /** - * + * * Provides representation of a client's registration metadata, to be shown from the dynamic registration endpoint * on the client_register and rotate_secret operations. - * + * * @author jricher * */ diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/HttpCodeView.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/HttpCodeView.java index aa45f78ec8..98f69c6622 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/HttpCodeView.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/HttpCodeView.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.view; diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonApprovedSiteView.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonApprovedSiteView.java index 09daa7944c..5db6ecff6c 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonApprovedSiteView.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonApprovedSiteView.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.view; @@ -61,40 +61,40 @@ public class JsonApprovedSiteView extends AbstractView { public static final String VIEWNAME = "jsonApprovedSiteView"; private Gson gson = new GsonBuilder() - .setExclusionStrategies(new ExclusionStrategy() { - - @Override - public boolean shouldSkipField(FieldAttributes f) { - - return false; - } - - @Override - public boolean shouldSkipClass(Class clazz) { - // skip the JPA binding wrapper - if (clazz.equals(BeanPropertyBindingResult.class)) { - return true; - } - return false; - } - - }) - .registerTypeAdapter(OAuth2AccessTokenEntity.class, new JsonSerializer() { - @Override - public JsonElement serialize(OAuth2AccessTokenEntity src, - Type typeOfSrc, JsonSerializationContext context) { - return new JsonPrimitive(src.getId()); - } - }) - .registerTypeAdapter(WhitelistedSite.class, new JsonSerializer() { - @Override - public JsonElement serialize(WhitelistedSite src, Type typeOfSrc, JsonSerializationContext context) { - return new JsonPrimitive(src.getId()); - } - }) - .serializeNulls() - .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") - .create(); + .setExclusionStrategies(new ExclusionStrategy() { + + @Override + public boolean shouldSkipField(FieldAttributes f) { + + return false; + } + + @Override + public boolean shouldSkipClass(Class clazz) { + // skip the JPA binding wrapper + if (clazz.equals(BeanPropertyBindingResult.class)) { + return true; + } + return false; + } + + }) + .registerTypeAdapter(OAuth2AccessTokenEntity.class, new JsonSerializer() { + @Override + public JsonElement serialize(OAuth2AccessTokenEntity src, + Type typeOfSrc, JsonSerializationContext context) { + return new JsonPrimitive(src.getId()); + } + }) + .registerTypeAdapter(WhitelistedSite.class, new JsonSerializer() { + @Override + public JsonElement serialize(WhitelistedSite src, Type typeOfSrc, JsonSerializationContext context) { + return new JsonPrimitive(src.getId()); + } + }) + .serializeNulls() + .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") + .create(); @Override protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) { diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonEntityView.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonEntityView.java index a5bbd6e7bf..b78a5f3c4c 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonEntityView.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonEntityView.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.view; @@ -56,27 +56,27 @@ public class JsonEntityView extends AbstractView { public static final String VIEWNAME = "jsonEntityView"; private Gson gson = new GsonBuilder() - .setExclusionStrategies(new ExclusionStrategy() { - - @Override - public boolean shouldSkipField(FieldAttributes f) { - - return false; - } - - @Override - public boolean shouldSkipClass(Class clazz) { - // skip the JPA binding wrapper - if (clazz.equals(BeanPropertyBindingResult.class)) { - return true; - } - return false; - } - - }) - .serializeNulls() - .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") - .create(); + .setExclusionStrategies(new ExclusionStrategy() { + + @Override + public boolean shouldSkipField(FieldAttributes f) { + + return false; + } + + @Override + public boolean shouldSkipClass(Class clazz) { + // skip the JPA binding wrapper + if (clazz.equals(BeanPropertyBindingResult.class)) { + return true; + } + return false; + } + + }) + .serializeNulls() + .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") + .create(); @Override protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) { diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonErrorView.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonErrorView.java index 2fa26dbacd..8ad0380cae 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonErrorView.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonErrorView.java @@ -46,12 +46,12 @@ public class JsonErrorView extends AbstractView { /** - * + * */ public static final String ERROR_MESSAGE = "errorMessage"; /** - * + * */ public static final String ERROR = "error"; @@ -63,27 +63,27 @@ public class JsonErrorView extends AbstractView { public static final String VIEWNAME = "jsonErrorView"; private Gson gson = new GsonBuilder() - .setExclusionStrategies(new ExclusionStrategy() { - - @Override - public boolean shouldSkipField(FieldAttributes f) { - - return false; - } - - @Override - public boolean shouldSkipClass(Class clazz) { - // skip the JPA binding wrapper - if (clazz.equals(BeanPropertyBindingResult.class)) { - return true; - } - return false; - } - - }) - .serializeNulls() - .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") - .create(); + .setExclusionStrategies(new ExclusionStrategy() { + + @Override + public boolean shouldSkipField(FieldAttributes f) { + + return false; + } + + @Override + public boolean shouldSkipClass(Class clazz) { + // skip the JPA binding wrapper + if (clazz.equals(BeanPropertyBindingResult.class)) { + return true; + } + return false; + } + + }) + .serializeNulls() + .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") + .create(); @Override protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) { diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoJWTView.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoJWTView.java index 405348de12..8996133927 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoJWTView.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoJWTView.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.view; @@ -99,11 +99,11 @@ protected void writeOut(JsonObject json, Map model, response.setContentType(JOSE_MEDIA_TYPE_VALUE); JWTClaimsSet claims = new JWTClaimsSet.Builder(JWTClaimsSet.parse(writer.toString())) - .audience(Lists.newArrayList(client.getClientId())) - .issuer(config.getIssuer()) - .issueTime(new Date()) - .jwtID(UUID.randomUUID().toString()) // set a random NONCE in the middle of it - .build(); + .audience(Lists.newArrayList(client.getClientId())) + .issuer(config.getIssuer()) + .issueTime(new Date()) + .jwtID(UUID.randomUUID().toString()) // set a random NONCE in the middle of it + .build(); if (client.getUserInfoEncryptedResponseAlg() != null && !client.getUserInfoEncryptedResponseAlg().equals(Algorithm.NONE) diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoView.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoView.java index 438a247e66..c1a4fa4df1 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoView.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoView.java @@ -85,7 +85,7 @@ public boolean shouldSkipClass(Class clazz) { /* * (non-Javadoc) - * + * * @see * org.springframework.web.servlet.view.AbstractView#renderMergedOutputModel * (java.util.Map, javax.servlet.http.HttpServletRequest, @@ -129,10 +129,10 @@ protected void writeOut(JsonObject json, Map model, HttpServletR /** * Build a JSON response according to the request object received. - * + * * Claims requested in requestObj.userinfo.claims are added to any * claims corresponding to requested scopes, if any. - * + * * @param ui the UserInfo to filter * @param scope the allowed scopes to filter by * @param authorizedClaims the claims authorized by the client or user @@ -169,7 +169,7 @@ private JsonObject toJsonFromRequestObj(UserInfo ui, Set scope, JsonObje } /** - * Pull the claims that have been targeted into a set for processing. + * Pull the claims that have been targeted into a set for processing. * Returns an empty set if the input is null. * @param claims the claims request to process */ diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ApprovedSiteAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ApprovedSiteAPI.java index 5843d37bf3..2bcb53cc61 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ApprovedSiteAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ApprovedSiteAPI.java @@ -15,14 +15,13 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.web; import java.security.Principal; import java.util.Collection; -import org.mitre.oauth2.service.OAuth2TokenEntityService; import org.mitre.openid.connect.model.ApprovedSite; import org.mitre.openid.connect.service.ApprovedSiteService; import org.mitre.openid.connect.view.HttpCodeView; @@ -55,9 +54,6 @@ public class ApprovedSiteAPI { @Autowired private ApprovedSiteService approvedSiteService; - @Autowired - private OAuth2TokenEntityService tokenServices; - /** * Logger for this class */ @@ -80,7 +76,7 @@ public String getAllApprovedSites(ModelMap m, Principal p) { /** * Delete an approved site - * + * */ @RequestMapping(value="/{id}", method = RequestMethod.DELETE) public String deleteApprovedSite(@PathVariable("id") Long id, ModelMap m, Principal p) { diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/AuthenticationTimeStamper.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/AuthenticationTimeStamper.java index 26824ed6d1..1acbc687f6 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/AuthenticationTimeStamper.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/AuthenticationTimeStamper.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.web; @@ -37,7 +37,7 @@ /** * This class sets a timestamp on the current HttpSession * when someone successfully authenticates. - * + * * @author jricher * */ diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/BlacklistAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/BlacklistAPI.java index d8635f7e8a..7a45907032 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/BlacklistAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/BlacklistAPI.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.web; @@ -168,7 +168,7 @@ public String updateBlacklistedSite(@PathVariable("id") Long id, @RequestBody St /** * Delete a blacklisted site - * + * */ @RequestMapping(value="/{id}", method = RequestMethod.DELETE) public String deleteBlacklistedSite(@PathVariable("id") Long id, ModelMap m) { diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java index 93accfe93e..7d924f14d8 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java @@ -134,7 +134,7 @@ public class ClientAPI { @Autowired private ClientLogoLoadingService clientLogoLoadingService; - + @Autowired @Qualifier("clientAssertionValidator") private AssertionValidator assertionValidator; @@ -142,76 +142,77 @@ public class ClientAPI { private JsonParser parser = new JsonParser(); private Gson gson = new GsonBuilder() - .serializeNulls() - .registerTypeAdapter(JWSAlgorithm.class, new JsonDeserializer() { - @Override - public JWSAlgorithm deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - if (json.isJsonPrimitive()) { - return JWSAlgorithm.parse(json.getAsString()); - } else { - return null; - } - } - }) - .registerTypeAdapter(JWEAlgorithm.class, new JsonDeserializer() { - @Override - public JWEAlgorithm deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - if (json.isJsonPrimitive()) { - return JWEAlgorithm.parse(json.getAsString()); - } else { - return null; - } - } - }) - .registerTypeAdapter(EncryptionMethod.class, new JsonDeserializer() { - @Override - public EncryptionMethod deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - if (json.isJsonPrimitive()) { - return EncryptionMethod.parse(json.getAsString()); - } else { - return null; - } - } - }) - .registerTypeAdapter(JWKSet.class, new JsonDeserializer() { - @Override - public JWKSet deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - if (json.isJsonObject()) { - try { - return JWKSet.parse(json.toString()); - } catch (ParseException e) { - return null; + .serializeNulls() + .registerTypeAdapter(JWSAlgorithm.class, new JsonDeserializer() { + @Override + public JWSAlgorithm deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + if (json.isJsonPrimitive()) { + return JWSAlgorithm.parse(json.getAsString()); + } else { + return null; + } } - } else { - return null; - } - } - }) - .registerTypeAdapter(JWT.class, new JsonDeserializer() { - @Override - public JWT deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - if (json.isJsonPrimitive()) { - try { - return JWTParser.parse(json.getAsString()); - } catch (ParseException e) { - return null; + }) + .registerTypeAdapter(JWEAlgorithm.class, new JsonDeserializer() { + @Override + public JWEAlgorithm deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + if (json.isJsonPrimitive()) { + return JWEAlgorithm.parse(json.getAsString()); + } else { + return null; + } } - } else { - return null; - } - } - }) - .registerTypeAdapter(PKCEAlgorithm.class, new JsonDeserializer() { - public PKCEAlgorithm deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - if (json.isJsonPrimitive()) { - return PKCEAlgorithm.parse(json.getAsString()); - } else { - return null; - } - } - }) - .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") - .create(); + }) + .registerTypeAdapter(EncryptionMethod.class, new JsonDeserializer() { + @Override + public EncryptionMethod deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + if (json.isJsonPrimitive()) { + return EncryptionMethod.parse(json.getAsString()); + } else { + return null; + } + } + }) + .registerTypeAdapter(JWKSet.class, new JsonDeserializer() { + @Override + public JWKSet deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + if (json.isJsonObject()) { + try { + return JWKSet.parse(json.toString()); + } catch (ParseException e) { + return null; + } + } else { + return null; + } + } + }) + .registerTypeAdapter(JWT.class, new JsonDeserializer() { + @Override + public JWT deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + if (json.isJsonPrimitive()) { + try { + return JWTParser.parse(json.getAsString()); + } catch (ParseException e) { + return null; + } + } else { + return null; + } + } + }) + .registerTypeAdapter(PKCEAlgorithm.class, new JsonDeserializer() { + @Override + public PKCEAlgorithm deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + if (json.isJsonPrimitive()) { + return PKCEAlgorithm.parse(json.getAsString()); + } else { + return null; + } + } + }) + .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") + .create(); /** * Logger for this class @@ -508,37 +509,37 @@ public String apiShowClient(@PathVariable("id") Long id, Model model, Authentica * Get the logo image for a client * @param id */ - @RequestMapping(value = "/{id}/logo", method=RequestMethod.GET, produces = { MediaType.IMAGE_GIF_VALUE, MediaType.IMAGE_JPEG_VALUE, MediaType.IMAGE_PNG_VALUE }) - public ResponseEntity getClientLogo(@PathVariable("id") Long id, Model model) { + @RequestMapping(value = "/{id}/logo", method=RequestMethod.GET, produces = { MediaType.IMAGE_GIF_VALUE, MediaType.IMAGE_JPEG_VALUE, MediaType.IMAGE_PNG_VALUE }) + public ResponseEntity getClientLogo(@PathVariable("id") Long id, Model model) { - ClientDetailsEntity client = clientService.getClientById(id); + ClientDetailsEntity client = clientService.getClientById(id); - if (client == null) { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } else if (Strings.isNullOrEmpty(client.getLogoUri())) { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } else { - // get the image from cache - CachedImage image = clientLogoLoadingService.getLogo(client); + if (client == null) { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } else if (Strings.isNullOrEmpty(client.getLogoUri())) { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } else { + // get the image from cache + CachedImage image = clientLogoLoadingService.getLogo(client); - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.parseMediaType(image.getContentType())); - headers.setContentLength(image.getLength()); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.parseMediaType(image.getContentType())); + headers.setContentLength(image.getLength()); - return new ResponseEntity<>(image.getData(), headers, HttpStatus.OK); - } - } - - private ClientDetailsEntity validateSoftwareStatement(ClientDetailsEntity newClient) throws ValidationException { - if (newClient.getSoftwareStatement() != null) { - if (assertionValidator.isValid(newClient.getSoftwareStatement())) { - // we have a software statement and its envelope passed all the checks from our validator - - // swap out all of the client's fields for the associated parts of the software statement - try { - JWTClaimsSet claimSet = newClient.getSoftwareStatement().getJWTClaimsSet(); - for (String claim : claimSet.getClaims().keySet()) { - switch (claim) { + return new ResponseEntity<>(image.getData(), headers, HttpStatus.OK); + } + } + + private ClientDetailsEntity validateSoftwareStatement(ClientDetailsEntity newClient) throws ValidationException { + if (newClient.getSoftwareStatement() != null) { + if (assertionValidator.isValid(newClient.getSoftwareStatement())) { + // we have a software statement and its envelope passed all the checks from our validator + + // swap out all of the client's fields for the associated parts of the software statement + try { + JWTClaimsSet claimSet = newClient.getSoftwareStatement().getJWTClaimsSet(); + for (String claim : claimSet.getClaims().keySet()) { + switch (claim) { case SOFTWARE_STATEMENT: throw new ValidationException("invalid_client_metadata", "Software statement can't include another software statement", HttpStatus.BAD_REQUEST); case CLAIMS_REDIRECT_URIS: @@ -610,7 +611,7 @@ private ClientDetailsEntity validateSoftwareStatement(ClientDetailsEntity newCli newClient.setJwks(JWKSet.parse(claimSet.getStringClaim(claim))); break; case POLICY_URI: - newClient.setPolicyUri(claimSet.getStringClaim(claim)); + newClient.setPolicyUri(claimSet.getStringClaim(claim)); break; case RESPONSE_TYPES: newClient.setResponseTypes(Sets.newHashSet(claimSet.getStringListClaim(claim))); @@ -650,21 +651,21 @@ private ClientDetailsEntity validateSoftwareStatement(ClientDetailsEntity newCli default: logger.warn("Software statement contained unknown field: " + claim + " with value " + claimSet.getClaim(claim)); break; - } } - - return newClient; - } catch (ParseException e) { - throw new ValidationException("invalid_client_metadata", "Software statement claims didn't parse", HttpStatus.BAD_REQUEST); } - } else { - throw new ValidationException("invalid_client_metadata", "Software statement rejected by validator", HttpStatus.BAD_REQUEST); + + return newClient; + } catch (ParseException e) { + throw new ValidationException("invalid_client_metadata", "Software statement claims didn't parse", HttpStatus.BAD_REQUEST); } } else { - // nothing to see here, carry on - return newClient; + throw new ValidationException("invalid_client_metadata", "Software statement rejected by validator", HttpStatus.BAD_REQUEST); } - + } else { + // nothing to see here, carry on + return newClient; } + } + } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DataAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DataAPI.java index 8f2667a3da..a95c5de96a 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DataAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DataAPI.java @@ -27,9 +27,6 @@ import org.mitre.openid.connect.config.ConfigurationPropertiesBean; import org.mitre.openid.connect.service.MITREidDataService; -import org.mitre.openid.connect.service.impl.MITREidDataService_1_0; -import org.mitre.openid.connect.service.impl.MITREidDataService_1_1; -import org.mitre.openid.connect.service.impl.MITREidDataService_1_2; import org.mitre.openid.connect.service.impl.MITREidDataService_1_3; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,9 +46,9 @@ /** * API endpoint for importing and exporting the current state of a server. * Includes all tokens, grants, whitelists, blacklists, and clients. - * + * * @author jricher - * + * */ @Controller @RequestMapping("/" + DataAPI.URL) @@ -72,13 +69,13 @@ public class DataAPI { @Autowired private List importers; - + private List supportedVersions = ImmutableList.of( - MITREidDataService.MITREID_CONNECT_1_0, - MITREidDataService.MITREID_CONNECT_1_1, - MITREidDataService.MITREID_CONNECT_1_2, - MITREidDataService.MITREID_CONNECT_1_3); - + MITREidDataService.MITREID_CONNECT_1_0, + MITREidDataService.MITREID_CONNECT_1_1, + MITREidDataService.MITREID_CONNECT_1_2, + MITREidDataService.MITREID_CONNECT_1_3); + @Autowired private MITREidDataService_1_3 exporter; @@ -92,31 +89,31 @@ public String importData(Reader in, Model m) throws IOException { while (reader.hasNext()) { JsonToken tok = reader.peek(); switch (tok) { - case NAME: - String name = reader.nextName(); - - if (supportedVersions.contains(name)) { - // we're working with a known data version tag - for (MITREidDataService dataService : importers) { - // dispatch to the correct service - if (dataService.supportsVersion(name)) { - dataService.importData(reader); - break; + case NAME: + String name = reader.nextName(); + + if (supportedVersions.contains(name)) { + // we're working with a known data version tag + for (MITREidDataService dataService : importers) { + // dispatch to the correct service + if (dataService.supportsVersion(name)) { + dataService.importData(reader); + break; + } } + } else { + // consume the next bit silently for now + logger.debug("Skipping value for " + name); // TODO: write these out? + reader.skipValue(); } - } else { - // consume the next bit silently for now - logger.debug("Skipping value for " + name); // TODO: write these out? - reader.skipValue(); - } - break; - case END_OBJECT: - break; - case END_DOCUMENT: - break; + break; + case END_OBJECT: + break; + case END_DOCUMENT: + break; } } - + reader.endObject(); return "httpCodeView"; diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java index afa4b6d70b..f99e5cc669 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java @@ -16,8 +16,6 @@ *******************************************************************************/ package org.mitre.openid.connect.web; -import static org.mitre.oauth2.model.RegisteredClientFields.*; - import java.io.UnsupportedEncodingException; import java.text.ParseException; import java.util.Date; @@ -26,7 +24,6 @@ import java.util.concurrent.TimeUnit; import org.mitre.jwt.assertion.AssertionValidator; -import org.mitre.jwt.signer.service.JWTSigningAndValidationService; import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.model.ClientDetailsEntity.AppType; import org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod; @@ -73,6 +70,45 @@ import com.nimbusds.jose.jwk.JWKSet; import com.nimbusds.jwt.JWTClaimsSet; +import static org.mitre.oauth2.model.RegisteredClientFields.APPLICATION_TYPE; +import static org.mitre.oauth2.model.RegisteredClientFields.CLAIMS_REDIRECT_URIS; +import static org.mitre.oauth2.model.RegisteredClientFields.CLIENT_ID; +import static org.mitre.oauth2.model.RegisteredClientFields.CLIENT_ID_ISSUED_AT; +import static org.mitre.oauth2.model.RegisteredClientFields.CLIENT_NAME; +import static org.mitre.oauth2.model.RegisteredClientFields.CLIENT_SECRET; +import static org.mitre.oauth2.model.RegisteredClientFields.CLIENT_SECRET_EXPIRES_AT; +import static org.mitre.oauth2.model.RegisteredClientFields.CLIENT_URI; +import static org.mitre.oauth2.model.RegisteredClientFields.CONTACTS; +import static org.mitre.oauth2.model.RegisteredClientFields.DEFAULT_ACR_VALUES; +import static org.mitre.oauth2.model.RegisteredClientFields.DEFAULT_MAX_AGE; +import static org.mitre.oauth2.model.RegisteredClientFields.GRANT_TYPES; +import static org.mitre.oauth2.model.RegisteredClientFields.ID_TOKEN_ENCRYPTED_RESPONSE_ALG; +import static org.mitre.oauth2.model.RegisteredClientFields.ID_TOKEN_ENCRYPTED_RESPONSE_ENC; +import static org.mitre.oauth2.model.RegisteredClientFields.ID_TOKEN_SIGNED_RESPONSE_ALG; +import static org.mitre.oauth2.model.RegisteredClientFields.INITIATE_LOGIN_URI; +import static org.mitre.oauth2.model.RegisteredClientFields.JWKS; +import static org.mitre.oauth2.model.RegisteredClientFields.JWKS_URI; +import static org.mitre.oauth2.model.RegisteredClientFields.LOGO_URI; +import static org.mitre.oauth2.model.RegisteredClientFields.POLICY_URI; +import static org.mitre.oauth2.model.RegisteredClientFields.POST_LOGOUT_REDIRECT_URIS; +import static org.mitre.oauth2.model.RegisteredClientFields.REDIRECT_URIS; +import static org.mitre.oauth2.model.RegisteredClientFields.REGISTRATION_ACCESS_TOKEN; +import static org.mitre.oauth2.model.RegisteredClientFields.REGISTRATION_CLIENT_URI; +import static org.mitre.oauth2.model.RegisteredClientFields.REQUEST_OBJECT_SIGNING_ALG; +import static org.mitre.oauth2.model.RegisteredClientFields.REQUEST_URIS; +import static org.mitre.oauth2.model.RegisteredClientFields.REQUIRE_AUTH_TIME; +import static org.mitre.oauth2.model.RegisteredClientFields.RESPONSE_TYPES; +import static org.mitre.oauth2.model.RegisteredClientFields.SCOPE; +import static org.mitre.oauth2.model.RegisteredClientFields.SECTOR_IDENTIFIER_URI; +import static org.mitre.oauth2.model.RegisteredClientFields.SOFTWARE_STATEMENT; +import static org.mitre.oauth2.model.RegisteredClientFields.SUBJECT_TYPE; +import static org.mitre.oauth2.model.RegisteredClientFields.TOKEN_ENDPOINT_AUTH_METHOD; +import static org.mitre.oauth2.model.RegisteredClientFields.TOKEN_ENDPOINT_AUTH_SIGNING_ALG; +import static org.mitre.oauth2.model.RegisteredClientFields.TOS_URI; +import static org.mitre.oauth2.model.RegisteredClientFields.USERINFO_ENCRYPTED_RESPONSE_ALG; +import static org.mitre.oauth2.model.RegisteredClientFields.USERINFO_ENCRYPTED_RESPONSE_ENC; +import static org.mitre.oauth2.model.RegisteredClientFields.USERINFO_SIGNED_RESPONSE_ALG; + @Controller @RequestMapping(value = DynamicClientRegistrationEndpoint.URL) public class DynamicClientRegistrationEndpoint { @@ -85,9 +121,6 @@ public class DynamicClientRegistrationEndpoint { @Autowired private OAuth2TokenEntityService tokenService; - @Autowired - private JWTSigningAndValidationService jwtService; - @Autowired private SystemScopeService scopeService; @@ -575,132 +608,132 @@ private ClientDetailsEntity validateAuth(ClientDetailsEntity newClient) throws V /** * @param newClient * @return - * @throws ValidationException + * @throws ValidationException */ private ClientDetailsEntity validateSoftwareStatement(ClientDetailsEntity newClient) throws ValidationException { if (newClient.getSoftwareStatement() != null) { if (assertionValidator.isValid(newClient.getSoftwareStatement())) { // we have a software statement and its envelope passed all the checks from our validator - + // swap out all of the client's fields for the associated parts of the software statement try { JWTClaimsSet claimSet = newClient.getSoftwareStatement().getJWTClaimsSet(); for (String claim : claimSet.getClaims().keySet()) { switch (claim) { - case SOFTWARE_STATEMENT: - throw new ValidationException("invalid_client_metadata", "Software statement can't include another software statement", HttpStatus.BAD_REQUEST); - case CLAIMS_REDIRECT_URIS: - newClient.setClaimsRedirectUris(Sets.newHashSet(claimSet.getStringListClaim(claim))); - break; - case CLIENT_SECRET_EXPIRES_AT: - throw new ValidationException("invalid_client_metadata", "Software statement can't include a client secret expiration time", HttpStatus.BAD_REQUEST); - case CLIENT_ID_ISSUED_AT: - throw new ValidationException("invalid_client_metadata", "Software statement can't include a client ID issuance time", HttpStatus.BAD_REQUEST); - case REGISTRATION_CLIENT_URI: - throw new ValidationException("invalid_client_metadata", "Software statement can't include a client configuration endpoint", HttpStatus.BAD_REQUEST); - case REGISTRATION_ACCESS_TOKEN: - throw new ValidationException("invalid_client_metadata", "Software statement can't include a client registration access token", HttpStatus.BAD_REQUEST); - case REQUEST_URIS: - newClient.setRequestUris(Sets.newHashSet(claimSet.getStringListClaim(claim))); - break; - case POST_LOGOUT_REDIRECT_URIS: - newClient.setPostLogoutRedirectUris(Sets.newHashSet(claimSet.getStringListClaim(claim))); - break; - case INITIATE_LOGIN_URI: - newClient.setInitiateLoginUri(claimSet.getStringClaim(claim)); - break; - case DEFAULT_ACR_VALUES: - newClient.setDefaultACRvalues(Sets.newHashSet(claimSet.getStringListClaim(claim))); - break; - case REQUIRE_AUTH_TIME: - newClient.setRequireAuthTime(claimSet.getBooleanClaim(claim)); - break; - case DEFAULT_MAX_AGE: - newClient.setDefaultMaxAge(claimSet.getIntegerClaim(claim)); - break; - case TOKEN_ENDPOINT_AUTH_SIGNING_ALG: - newClient.setTokenEndpointAuthSigningAlg(JWSAlgorithm.parse(claimSet.getStringClaim(claim))); - break; - case ID_TOKEN_ENCRYPTED_RESPONSE_ENC: - newClient.setIdTokenEncryptedResponseEnc(EncryptionMethod.parse(claimSet.getStringClaim(claim))); - break; - case ID_TOKEN_ENCRYPTED_RESPONSE_ALG: - newClient.setIdTokenEncryptedResponseAlg(JWEAlgorithm.parse(claimSet.getStringClaim(claim))); - break; - case ID_TOKEN_SIGNED_RESPONSE_ALG: - newClient.setIdTokenSignedResponseAlg(JWSAlgorithm.parse(claimSet.getStringClaim(claim))); - break; - case USERINFO_ENCRYPTED_RESPONSE_ENC: - newClient.setUserInfoEncryptedResponseEnc(EncryptionMethod.parse(claimSet.getStringClaim(claim))); - break; - case USERINFO_ENCRYPTED_RESPONSE_ALG: - newClient.setUserInfoEncryptedResponseAlg(JWEAlgorithm.parse(claimSet.getStringClaim(claim))); - break; - case USERINFO_SIGNED_RESPONSE_ALG: - newClient.setUserInfoSignedResponseAlg(JWSAlgorithm.parse(claimSet.getStringClaim(claim))); - break; - case REQUEST_OBJECT_SIGNING_ALG: - newClient.setRequestObjectSigningAlg(JWSAlgorithm.parse(claimSet.getStringClaim(claim))); - break; - case SUBJECT_TYPE: - newClient.setSubjectType(SubjectType.getByValue(claimSet.getStringClaim(claim))); - break; - case SECTOR_IDENTIFIER_URI: - newClient.setSectorIdentifierUri(claimSet.getStringClaim(claim)); - break; - case APPLICATION_TYPE: - newClient.setApplicationType(AppType.getByValue(claimSet.getStringClaim(claim))); - break; - case JWKS_URI: - newClient.setJwksUri(claimSet.getStringClaim(claim)); - break; - case JWKS: - newClient.setJwks(JWKSet.parse(claimSet.getStringClaim(claim))); - break; - case POLICY_URI: - newClient.setPolicyUri(claimSet.getStringClaim(claim)); - break; - case RESPONSE_TYPES: - newClient.setResponseTypes(Sets.newHashSet(claimSet.getStringListClaim(claim))); - break; - case GRANT_TYPES: - newClient.setGrantTypes(Sets.newHashSet(claimSet.getStringListClaim(claim))); - break; - case SCOPE: - newClient.setScope(OAuth2Utils.parseParameterList(claimSet.getStringClaim(claim))); - break; - case TOKEN_ENDPOINT_AUTH_METHOD: - newClient.setTokenEndpointAuthMethod(AuthMethod.getByValue(claimSet.getStringClaim(claim))); - break; - case TOS_URI: - newClient.setTosUri(claimSet.getStringClaim(claim)); - break; - case CONTACTS: - newClient.setContacts(Sets.newHashSet(claimSet.getStringListClaim(claim))); - break; - case LOGO_URI: - newClient.setLogoUri(claimSet.getStringClaim(claim)); - break; - case CLIENT_URI: - newClient.setClientUri(claimSet.getStringClaim(claim)); - break; - case CLIENT_NAME: - newClient.setClientName(claimSet.getStringClaim(claim)); - break; - case REDIRECT_URIS: - newClient.setRedirectUris(Sets.newHashSet(claimSet.getStringListClaim(claim))); - break; - case CLIENT_SECRET: - throw new ValidationException("invalid_client_metadata", "Software statement can't contain client secret", HttpStatus.BAD_REQUEST); - case CLIENT_ID: - throw new ValidationException("invalid_client_metadata", "Software statement can't contain client ID", HttpStatus.BAD_REQUEST); - - default: - logger.warn("Software statement contained unknown field: " + claim + " with value " + claimSet.getClaim(claim)); - break; + case SOFTWARE_STATEMENT: + throw new ValidationException("invalid_client_metadata", "Software statement can't include another software statement", HttpStatus.BAD_REQUEST); + case CLAIMS_REDIRECT_URIS: + newClient.setClaimsRedirectUris(Sets.newHashSet(claimSet.getStringListClaim(claim))); + break; + case CLIENT_SECRET_EXPIRES_AT: + throw new ValidationException("invalid_client_metadata", "Software statement can't include a client secret expiration time", HttpStatus.BAD_REQUEST); + case CLIENT_ID_ISSUED_AT: + throw new ValidationException("invalid_client_metadata", "Software statement can't include a client ID issuance time", HttpStatus.BAD_REQUEST); + case REGISTRATION_CLIENT_URI: + throw new ValidationException("invalid_client_metadata", "Software statement can't include a client configuration endpoint", HttpStatus.BAD_REQUEST); + case REGISTRATION_ACCESS_TOKEN: + throw new ValidationException("invalid_client_metadata", "Software statement can't include a client registration access token", HttpStatus.BAD_REQUEST); + case REQUEST_URIS: + newClient.setRequestUris(Sets.newHashSet(claimSet.getStringListClaim(claim))); + break; + case POST_LOGOUT_REDIRECT_URIS: + newClient.setPostLogoutRedirectUris(Sets.newHashSet(claimSet.getStringListClaim(claim))); + break; + case INITIATE_LOGIN_URI: + newClient.setInitiateLoginUri(claimSet.getStringClaim(claim)); + break; + case DEFAULT_ACR_VALUES: + newClient.setDefaultACRvalues(Sets.newHashSet(claimSet.getStringListClaim(claim))); + break; + case REQUIRE_AUTH_TIME: + newClient.setRequireAuthTime(claimSet.getBooleanClaim(claim)); + break; + case DEFAULT_MAX_AGE: + newClient.setDefaultMaxAge(claimSet.getIntegerClaim(claim)); + break; + case TOKEN_ENDPOINT_AUTH_SIGNING_ALG: + newClient.setTokenEndpointAuthSigningAlg(JWSAlgorithm.parse(claimSet.getStringClaim(claim))); + break; + case ID_TOKEN_ENCRYPTED_RESPONSE_ENC: + newClient.setIdTokenEncryptedResponseEnc(EncryptionMethod.parse(claimSet.getStringClaim(claim))); + break; + case ID_TOKEN_ENCRYPTED_RESPONSE_ALG: + newClient.setIdTokenEncryptedResponseAlg(JWEAlgorithm.parse(claimSet.getStringClaim(claim))); + break; + case ID_TOKEN_SIGNED_RESPONSE_ALG: + newClient.setIdTokenSignedResponseAlg(JWSAlgorithm.parse(claimSet.getStringClaim(claim))); + break; + case USERINFO_ENCRYPTED_RESPONSE_ENC: + newClient.setUserInfoEncryptedResponseEnc(EncryptionMethod.parse(claimSet.getStringClaim(claim))); + break; + case USERINFO_ENCRYPTED_RESPONSE_ALG: + newClient.setUserInfoEncryptedResponseAlg(JWEAlgorithm.parse(claimSet.getStringClaim(claim))); + break; + case USERINFO_SIGNED_RESPONSE_ALG: + newClient.setUserInfoSignedResponseAlg(JWSAlgorithm.parse(claimSet.getStringClaim(claim))); + break; + case REQUEST_OBJECT_SIGNING_ALG: + newClient.setRequestObjectSigningAlg(JWSAlgorithm.parse(claimSet.getStringClaim(claim))); + break; + case SUBJECT_TYPE: + newClient.setSubjectType(SubjectType.getByValue(claimSet.getStringClaim(claim))); + break; + case SECTOR_IDENTIFIER_URI: + newClient.setSectorIdentifierUri(claimSet.getStringClaim(claim)); + break; + case APPLICATION_TYPE: + newClient.setApplicationType(AppType.getByValue(claimSet.getStringClaim(claim))); + break; + case JWKS_URI: + newClient.setJwksUri(claimSet.getStringClaim(claim)); + break; + case JWKS: + newClient.setJwks(JWKSet.parse(claimSet.getStringClaim(claim))); + break; + case POLICY_URI: + newClient.setPolicyUri(claimSet.getStringClaim(claim)); + break; + case RESPONSE_TYPES: + newClient.setResponseTypes(Sets.newHashSet(claimSet.getStringListClaim(claim))); + break; + case GRANT_TYPES: + newClient.setGrantTypes(Sets.newHashSet(claimSet.getStringListClaim(claim))); + break; + case SCOPE: + newClient.setScope(OAuth2Utils.parseParameterList(claimSet.getStringClaim(claim))); + break; + case TOKEN_ENDPOINT_AUTH_METHOD: + newClient.setTokenEndpointAuthMethod(AuthMethod.getByValue(claimSet.getStringClaim(claim))); + break; + case TOS_URI: + newClient.setTosUri(claimSet.getStringClaim(claim)); + break; + case CONTACTS: + newClient.setContacts(Sets.newHashSet(claimSet.getStringListClaim(claim))); + break; + case LOGO_URI: + newClient.setLogoUri(claimSet.getStringClaim(claim)); + break; + case CLIENT_URI: + newClient.setClientUri(claimSet.getStringClaim(claim)); + break; + case CLIENT_NAME: + newClient.setClientName(claimSet.getStringClaim(claim)); + break; + case REDIRECT_URIS: + newClient.setRedirectUris(Sets.newHashSet(claimSet.getStringListClaim(claim))); + break; + case CLIENT_SECRET: + throw new ValidationException("invalid_client_metadata", "Software statement can't contain client secret", HttpStatus.BAD_REQUEST); + case CLIENT_ID: + throw new ValidationException("invalid_client_metadata", "Software statement can't contain client ID", HttpStatus.BAD_REQUEST); + + default: + logger.warn("Software statement contained unknown field: " + claim + " with value " + claimSet.getClaim(claim)); + break; } } - + return newClient; } catch (ParseException e) { throw new ValidationException("invalid_client_metadata", "Software statement claims didn't parse", HttpStatus.BAD_REQUEST); @@ -712,10 +745,10 @@ private ClientDetailsEntity validateSoftwareStatement(ClientDetailsEntity newCli // nothing to see here, carry on return newClient; } - + } - + /* * Rotates the registration token if it's expired, otherwise returns it */ diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ProtectedResourceRegistrationEndpoint.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ProtectedResourceRegistrationEndpoint.java index 938957af0a..947dfe092f 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ProtectedResourceRegistrationEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ProtectedResourceRegistrationEndpoint.java @@ -22,7 +22,6 @@ import java.util.HashSet; import java.util.Set; -import org.mitre.jwt.signer.service.JWTSigningAndValidationService; import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod; import org.mitre.oauth2.model.OAuth2AccessTokenEntity; @@ -34,7 +33,6 @@ import org.mitre.openid.connect.ClientDetailsEntityJsonProcessor; import org.mitre.openid.connect.config.ConfigurationPropertiesBean; import org.mitre.openid.connect.exception.ValidationException; -import org.mitre.openid.connect.service.BlacklistedSiteService; import org.mitre.openid.connect.service.OIDCTokenService; import org.mitre.openid.connect.view.ClientInformationResponseView; import org.mitre.openid.connect.view.HttpCodeView; @@ -63,7 +61,7 @@ public class ProtectedResourceRegistrationEndpoint { /** - * + * */ public static final String URL = "resource"; @@ -73,15 +71,9 @@ public class ProtectedResourceRegistrationEndpoint { @Autowired private OAuth2TokenEntityService tokenService; - @Autowired - private JWTSigningAndValidationService jwtService; - @Autowired private SystemScopeService scopeService; - @Autowired - private BlacklistedSiteService blacklistService; - @Autowired private ConfigurationPropertiesBean config; diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ServerConfigInterceptor.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ServerConfigInterceptor.java index 321d7b7633..812bbd69d4 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ServerConfigInterceptor.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ServerConfigInterceptor.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.web; @@ -28,10 +28,10 @@ import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; /** - * + * * Injects the server configuration bean into the request context. * This allows JSPs and the like to call "config.logoUrl" among others. - * + * * @author jricher * */ @@ -39,7 +39,7 @@ public class ServerConfigInterceptor extends HandlerInterceptorAdapter { @Autowired private ConfigurationPropertiesBean config; - + @Autowired private UIConfiguration ui; diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/StatsAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/StatsAPI.java index 7bbb44c711..4f5ae9b14b 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/StatsAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/StatsAPI.java @@ -54,16 +54,16 @@ public String statsSummary(ModelMap m) { } -// @PreAuthorize("hasRole('ROLE_USER')") -// @RequestMapping(value = "byclientid", produces = MediaType.APPLICATION_JSON_VALUE) -// public String statsByClient(ModelMap m) { -// Map e = statsService.getByClientId(); -// -// m.put(JsonEntityView.ENTITY, e); -// -// return JsonEntityView.VIEWNAME; -// } -// + // @PreAuthorize("hasRole('ROLE_USER')") + // @RequestMapping(value = "byclientid", produces = MediaType.APPLICATION_JSON_VALUE) + // public String statsByClient(ModelMap m) { + // Map e = statsService.getByClientId(); + // + // m.put(JsonEntityView.ENTITY, e); + // + // return JsonEntityView.VIEWNAME; + // } + // @PreAuthorize("hasRole('ROLE_USER')") @RequestMapping(value = "byclientid/{id}", produces = MediaType.APPLICATION_JSON_VALUE) public String statsByClientId(@PathVariable("id") String clientId, ModelMap m) { diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/UserInfoEndpoint.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/UserInfoEndpoint.java index 19d01c6280..a50a38abf2 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/UserInfoEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/UserInfoEndpoint.java @@ -45,7 +45,7 @@ /** * OpenID Connect UserInfo endpoint, as specified in Standard sec 5 and Messages sec 2.4. - * + * * @author AANGANES * */ diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/WhitelistAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/WhitelistAPI.java index f9196b01ff..5cd0a723c0 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/WhitelistAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/WhitelistAPI.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.web; @@ -168,7 +168,7 @@ public String updateWhitelistedSite(@PathVariable("id") Long id, @RequestBody St /** * Delete a whitelisted site - * + * */ @PreAuthorize("hasRole('ROLE_ADMIN')") @RequestMapping(value="/{id}", method = RequestMethod.DELETE) diff --git a/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestBlacklistAwareRedirectResolver.java b/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestBlacklistAwareRedirectResolver.java index 16497e36ab..40daba48c3 100644 --- a/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestBlacklistAwareRedirectResolver.java +++ b/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestBlacklistAwareRedirectResolver.java @@ -17,6 +17,8 @@ package org.mitre.oauth2.service.impl; +import static org.mockito.Matchers.anyString; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -33,8 +35,6 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.mockito.Matchers.anyString; - import static org.mockito.Mockito.when; import static org.junit.Assert.assertThat; @@ -54,7 +54,7 @@ public class TestBlacklistAwareRedirectResolver { @Mock private ConfigurationPropertiesBean config; - + @InjectMocks private BlacklistAwareRedirectResolver resolver; @@ -133,7 +133,7 @@ public void testRedirectMatches_default() { assertThat(res2, is(true)); } - + @Test public void testHeartMode() { when(config.isHeartMode()).thenReturn(true); diff --git a/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultIntrospectionResultAssembler.java b/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultIntrospectionResultAssembler.java index dba6bb1b4a..29e63039bb 100644 --- a/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultIntrospectionResultAssembler.java +++ b/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultIntrospectionResultAssembler.java @@ -16,6 +16,9 @@ *******************************************************************************/ package org.mitre.oauth2.service.impl; +import static com.google.common.collect.Sets.newHashSet; +import static org.mockito.BDDMockito.given; + import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; @@ -38,13 +41,9 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import static com.google.common.collect.Sets.newHashSet; - import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.mockito.BDDMockito.given; - import static org.mockito.Mockito.RETURNS_DEEP_STUBS; import static org.mockito.Mockito.mock; @@ -61,7 +60,7 @@ public void shouldAssembleExpectedResultForAccessToken() throws ParseException { // given OAuth2AccessTokenEntity accessToken = accessToken(new Date(123 * 1000L), scopes("foo", "bar"), null, "Bearer", - oauth2AuthenticationWithUser(oauth2Request("clientId"), "name")); + oauth2AuthenticationWithUser(oauth2Request("clientId"), "name")); UserInfo userInfo = userInfo("sub"); @@ -91,7 +90,7 @@ public void shouldAssembleExpectedResultForAccessToken_withPermissions() throws // given OAuth2AccessTokenEntity accessToken = accessToken(new Date(123 * 1000L), scopes("foo", "bar"), permissions(permission(1L, "foo", "bar")), - "Bearer", oauth2AuthenticationWithUser(oauth2Request("clientId"), "name")); + "Bearer", oauth2AuthenticationWithUser(oauth2Request("clientId"), "name")); UserInfo userInfo = userInfo("sub"); @@ -156,7 +155,7 @@ public void shouldAssembleExpectedResultForAccessTokenWithoutExpiry() { // given OAuth2AccessTokenEntity accessToken = accessToken(null, scopes("foo", "bar"), null, "Bearer", - oauth2AuthenticationWithUser(oauth2Request("clientId"), "name")); + oauth2AuthenticationWithUser(oauth2Request("clientId"), "name")); UserInfo userInfo = userInfo("sub"); @@ -179,36 +178,36 @@ public void shouldAssembleExpectedResultForAccessTokenWithoutExpiry() { } @Test - public void shouldAssembleExpectedResultForAccessTokenWithoutUserAuthentication() throws ParseException { - // given - OAuth2AccessTokenEntity accessToken = accessToken(new Date(123 * 1000L), scopes("foo", "bar"), null, "Bearer", - oauth2Authentication(oauth2Request("clientId"), null)); - - Set authScopes = scopes("foo", "bar", "baz"); - - // when - Map result = assembler.assembleFrom(accessToken, null, authScopes); - - - // then `user_id` should not be present - Map expected = new ImmutableMap.Builder() - .put("sub", "clientId") - .put("exp", 123L) - .put("expires_at", dateFormat.valueToString(new Date(123 * 1000L))) - .put("scope", "bar foo") - .put("active", Boolean.TRUE) - .put("client_id", "clientId") - .put("token_type", "Bearer") - .build(); - assertThat(result, is(equalTo(expected))); - } + public void shouldAssembleExpectedResultForAccessTokenWithoutUserAuthentication() throws ParseException { + // given + OAuth2AccessTokenEntity accessToken = accessToken(new Date(123 * 1000L), scopes("foo", "bar"), null, "Bearer", + oauth2Authentication(oauth2Request("clientId"), null)); + + Set authScopes = scopes("foo", "bar", "baz"); + + // when + Map result = assembler.assembleFrom(accessToken, null, authScopes); + + + // then `user_id` should not be present + Map expected = new ImmutableMap.Builder() + .put("sub", "clientId") + .put("exp", 123L) + .put("expires_at", dateFormat.valueToString(new Date(123 * 1000L))) + .put("scope", "bar foo") + .put("active", Boolean.TRUE) + .put("client_id", "clientId") + .put("token_type", "Bearer") + .build(); + assertThat(result, is(equalTo(expected))); + } @Test public void shouldAssembleExpectedResultForRefreshToken() throws ParseException { // given OAuth2RefreshTokenEntity refreshToken = refreshToken(new Date(123 * 1000L), - oauth2AuthenticationWithUser(oauth2Request("clientId", scopes("foo", "bar")), "name")); + oauth2AuthenticationWithUser(oauth2Request("clientId", scopes("foo", "bar")), "name")); UserInfo userInfo = userInfo("sub"); @@ -283,27 +282,27 @@ public void shouldAssembleExpectedResultForRefreshTokenWithoutExpiry() { assertThat(result, is(equalTo(expected))); } - @Test - public void shouldAssembleExpectedResultForRefreshTokenWithoutUserAuthentication() throws ParseException { - // given - OAuth2RefreshTokenEntity refreshToken = refreshToken(null, - oauth2Authentication(oauth2Request("clientId", scopes("foo", "bar")), null)); + @Test + public void shouldAssembleExpectedResultForRefreshTokenWithoutUserAuthentication() throws ParseException { + // given + OAuth2RefreshTokenEntity refreshToken = refreshToken(null, + oauth2Authentication(oauth2Request("clientId", scopes("foo", "bar")), null)); - Set authScopes = scopes("foo", "bar", "baz"); + Set authScopes = scopes("foo", "bar", "baz"); - // when - Map result = assembler.assembleFrom(refreshToken, null, authScopes); + // when + Map result = assembler.assembleFrom(refreshToken, null, authScopes); - // then `user_id` should not be present - Map expected = new ImmutableMap.Builder() - .put("sub", "clientId") - .put("scope", "bar foo") - .put("active", Boolean.TRUE) - .put("client_id", "clientId") - .build(); - assertThat(result, is(equalTo(expected))); - } + // then `user_id` should not be present + Map expected = new ImmutableMap.Builder() + .put("sub", "clientId") + .put("scope", "bar foo") + .put("active", Boolean.TRUE) + .put("client_id", "clientId") + .build(); + assertThat(result, is(equalTo(expected))); + } @@ -332,12 +331,12 @@ private OAuth2RefreshTokenEntity refreshToken(Date exp, OAuth2Authentication aut private OAuth2Authentication oauth2AuthenticationWithUser(OAuth2Request request, String username) { UsernamePasswordAuthenticationToken userAuthentication = new UsernamePasswordAuthenticationToken(username, "somepassword"); - return oauth2Authentication(request, userAuthentication); + return oauth2Authentication(request, userAuthentication); } - private OAuth2Authentication oauth2Authentication(OAuth2Request request, Authentication userAuthentication) { - return new OAuth2Authentication(request, userAuthentication); - } + private OAuth2Authentication oauth2Authentication(OAuth2Request request, Authentication userAuthentication) { + return new OAuth2Authentication(request, userAuthentication); + } private OAuth2Request oauth2Request(String clientId) { return oauth2Request(clientId, null); diff --git a/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultOAuth2ClientDetailsEntityService.java b/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultOAuth2ClientDetailsEntityService.java index fabe080ca0..40bdcd496c 100644 --- a/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultOAuth2ClientDetailsEntityService.java +++ b/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultOAuth2ClientDetailsEntityService.java @@ -16,8 +16,6 @@ *******************************************************************************/ package org.mitre.oauth2.service.impl; -import static org.mockito.Matchers.anyString; - import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; @@ -51,7 +49,6 @@ import com.google.common.collect.Sets; -import static org.hamcrest.CoreMatchers.any; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; @@ -90,7 +87,7 @@ public class TestDefaultOAuth2ClientDetailsEntityService { @Mock private StatsService statsService; - + @Mock private ConfigurationPropertiesBean config; @@ -145,7 +142,7 @@ public Set answer(InvocationOnMock invocation) throws Throwable { // we're not testing reserved scopes here, just pass through when it's called Mockito.when(scopeService.removeReservedScopes(Matchers.anySet())).then(AdditionalAnswers.returnsFirstArg()); - + Mockito.when(config.isHeartMode()).thenReturn(false); } @@ -365,7 +362,7 @@ public void updateClient_noOfflineAccess() { assertThat(client.getScope().contains(SystemScopeService.OFFLINE_ACCESS), is(equalTo(false))); } - + @Test(expected = IllegalArgumentException.class) public void heartMode_authcode_invalidGrants() { Mockito.when(config.isHeartMode()).thenReturn(true); @@ -378,15 +375,15 @@ public void heartMode_authcode_invalidGrants() { client.setGrantTypes(grantTypes); client.setTokenEndpointAuthMethod(AuthMethod.PRIVATE_KEY); - + client.setRedirectUris(Sets.newHashSet("https://foo.bar/")); client.setJwksUri("https://foo.bar/jwks"); - + service.saveNewClient(client); - + } - + @Test(expected = IllegalArgumentException.class) public void heartMode_implicit_invalidGrants() { Mockito.when(config.isHeartMode()).thenReturn(true); @@ -399,13 +396,13 @@ public void heartMode_implicit_invalidGrants() { client.setGrantTypes(grantTypes); client.setTokenEndpointAuthMethod(AuthMethod.NONE); - + client.setRedirectUris(Sets.newHashSet("https://foo.bar/")); client.setJwksUri("https://foo.bar/jwks"); - + service.saveNewClient(client); - + } @Test(expected = IllegalArgumentException.class) @@ -420,11 +417,11 @@ public void heartMode_clientcreds_invalidGrants() { client.setGrantTypes(grantTypes); client.setTokenEndpointAuthMethod(AuthMethod.PRIVATE_KEY); - + client.setJwksUri("https://foo.bar/jwks"); - + service.saveNewClient(client); - + } @Test(expected = IllegalArgumentException.class) @@ -435,17 +432,17 @@ public void heartMode_authcode_authMethod() { Set grantTypes = new LinkedHashSet<>(); grantTypes.add("authorization_code"); client.setGrantTypes(grantTypes); - + client.setTokenEndpointAuthMethod(AuthMethod.SECRET_POST); client.setRedirectUris(Sets.newHashSet("https://foo.bar/")); client.setJwksUri("https://foo.bar/jwks"); - + service.saveNewClient(client); - + } - + @Test(expected = IllegalArgumentException.class) public void heartMode_implicit_authMethod() { Mockito.when(config.isHeartMode()).thenReturn(true); @@ -460,9 +457,9 @@ public void heartMode_implicit_authMethod() { client.setRedirectUris(Sets.newHashSet("https://foo.bar/")); client.setJwksUri("https://foo.bar/jwks"); - + service.saveNewClient(client); - + } @Test(expected = IllegalArgumentException.class) @@ -475,13 +472,13 @@ public void heartMode_clientcreds_authMethod() { client.setGrantTypes(grantTypes); client.setTokenEndpointAuthMethod(AuthMethod.SECRET_BASIC); - + client.setRedirectUris(Sets.newHashSet("https://foo.bar/")); client.setJwksUri("https://foo.bar/jwks"); service.saveNewClient(client); - + } @Test(expected = IllegalArgumentException.class) @@ -492,13 +489,13 @@ public void heartMode_authcode_redirectUris() { Set grantTypes = new LinkedHashSet<>(); grantTypes.add("authorization_code"); client.setGrantTypes(grantTypes); - + client.setTokenEndpointAuthMethod(AuthMethod.PRIVATE_KEY); service.saveNewClient(client); - + } - + @Test(expected = IllegalArgumentException.class) public void heartMode_implicit_redirectUris() { Mockito.when(config.isHeartMode()).thenReturn(true); @@ -511,7 +508,7 @@ public void heartMode_implicit_redirectUris() { client.setTokenEndpointAuthMethod(AuthMethod.NONE); service.saveNewClient(client); - + } @Test(expected = IllegalArgumentException.class) @@ -528,7 +525,7 @@ public void heartMode_clientcreds_redirectUris() { client.setRedirectUris(Sets.newHashSet("http://foo.bar/")); service.saveNewClient(client); - + } @Test(expected = IllegalArgumentException.class) @@ -539,15 +536,15 @@ public void heartMode_clientSecret() { Set grantTypes = new LinkedHashSet<>(); grantTypes.add("authorization_code"); client.setGrantTypes(grantTypes); - + client.setTokenEndpointAuthMethod(AuthMethod.PRIVATE_KEY); - + client.setRedirectUris(Sets.newHashSet("http://foo.bar/")); client.setClientSecret("secret!"); - + service.saveNewClient(client); - + } @Test(expected = IllegalArgumentException.class) @@ -558,18 +555,18 @@ public void heartMode_noJwks() { Set grantTypes = new LinkedHashSet<>(); grantTypes.add("authorization_code"); client.setGrantTypes(grantTypes); - + client.setTokenEndpointAuthMethod(AuthMethod.PRIVATE_KEY); - + client.setRedirectUris(Sets.newHashSet("https://foo.bar/")); client.setJwks(null); client.setJwksUri(null); - + service.saveNewClient(client); - + } - + @Test public void heartMode_validAuthcodeClient() { Mockito.when(config.isHeartMode()).thenReturn(true); @@ -579,19 +576,19 @@ public void heartMode_validAuthcodeClient() { grantTypes.add("authorization_code"); grantTypes.add("refresh_token"); client.setGrantTypes(grantTypes); - + client.setTokenEndpointAuthMethod(AuthMethod.PRIVATE_KEY); - + client.setRedirectUris(Sets.newHashSet("https://foo.bar/")); client.setJwksUri("https://foo.bar/jwks"); - + service.saveNewClient(client); - + assertThat(client.getClientId(), is(notNullValue(String.class))); assertThat(client.getClientSecret(), is(nullValue())); } - + @Test(expected = IllegalArgumentException.class) public void heartMode_nonLocalHttpRedirect() { Mockito.when(config.isHeartMode()).thenReturn(true); @@ -601,17 +598,17 @@ public void heartMode_nonLocalHttpRedirect() { grantTypes.add("authorization_code"); grantTypes.add("refresh_token"); client.setGrantTypes(grantTypes); - + client.setTokenEndpointAuthMethod(AuthMethod.PRIVATE_KEY); - + client.setRedirectUris(Sets.newHashSet("http://foo.bar/")); client.setJwksUri("https://foo.bar/jwks"); - + service.saveNewClient(client); - + } - + @Test(expected = IllegalArgumentException.class) public void heartMode_multipleRedirectClass() { Mockito.when(config.isHeartMode()).thenReturn(true); @@ -621,14 +618,14 @@ public void heartMode_multipleRedirectClass() { grantTypes.add("authorization_code"); grantTypes.add("refresh_token"); client.setGrantTypes(grantTypes); - + client.setTokenEndpointAuthMethod(AuthMethod.PRIVATE_KEY); - + client.setRedirectUris(Sets.newHashSet("http://localhost/", "https://foo.bar", "foo://bar")); client.setJwksUri("https://foo.bar/jwks"); - + service.saveNewClient(client); - + } } diff --git a/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultSystemScopeService.java b/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultSystemScopeService.java index e78516b4d2..1643ec4c5d 100644 --- a/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultSystemScopeService.java +++ b/openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultSystemScopeService.java @@ -26,9 +26,7 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; -import org.mockito.stubbing.Answer; import com.google.common.collect.Sets; diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultApprovedSiteService.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultApprovedSiteService.java index 262599a8aa..5b9b4058ea 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultApprovedSiteService.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultApprovedSiteService.java @@ -16,7 +16,8 @@ *******************************************************************************/ package org.mitre.openid.connect.service.impl; -import java.util.ArrayList; +import static org.mockito.Matchers.any; + import java.util.HashSet; import java.util.List; import java.util.Set; @@ -40,8 +41,6 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Sets; -import static org.mockito.Matchers.any; - import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; @@ -60,7 +59,7 @@ public class TestDefaultApprovedSiteService { @Mock private OAuth2TokenRepository tokenRepository; - + @Mock private StatsService statsService; diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultStatsService.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultStatsService.java index 930e659558..b8d19f2351 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultStatsService.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultStatsService.java @@ -23,7 +23,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mitre.oauth2.model.ClientDetailsEntity; -import org.mitre.oauth2.service.ClientDetailsEntityService; import org.mitre.openid.connect.model.ApprovedSite; import org.mitre.openid.connect.service.ApprovedSiteService; import org.mockito.InjectMocks; diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultUserInfoService.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultUserInfoService.java index 6808180747..628b28892c 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultUserInfoService.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestDefaultUserInfoService.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.service.impl; diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_0.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_0.java index d3e88207e8..96fdf2ad74 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_0.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_0.java @@ -16,6 +16,11 @@ *******************************************************************************/ package org.mitre.openid.connect.service.impl; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.isA; +import static org.mockito.Matchers.isNull; + import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; @@ -73,11 +78,6 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.isA; -import static org.mockito.Matchers.isNull; - import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_1.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_1.java index ccdde67edc..cb389a3d9a 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_1.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_1.java @@ -16,6 +16,11 @@ *******************************************************************************/ package org.mitre.openid.connect.service.impl; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.isA; +import static org.mockito.Matchers.isNull; + import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; @@ -72,11 +77,6 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.isA; -import static org.mockito.Matchers.isNull; - import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_2.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_2.java index b7c0a2fd0b..240e7fa8e4 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_2.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_2.java @@ -16,9 +16,13 @@ *******************************************************************************/ package org.mitre.openid.connect.service.impl; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.isA; +import static org.mockito.Matchers.isNull; + import java.io.IOException; import java.io.StringReader; -import java.io.StringWriter; import java.text.ParseException; import java.util.ArrayList; import java.util.Collections; @@ -62,42 +66,27 @@ import org.slf4j.LoggerFactory; import org.springframework.format.annotation.DateTimeFormat.ISO; import org.springframework.format.datetime.DateFormatter; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.gson.JsonArray; import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; import com.nimbusds.jwt.JWTParser; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.isA; -import static org.mockito.Matchers.isNull; - import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.Mockito.withSettings; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; @RunWith(MockitoJUnitRunner.class) @SuppressWarnings(value = {"rawtypes", "unchecked"}) diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_3.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_3.java index 762b9ff695..d84bbfaef6 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_3.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_3.java @@ -16,6 +16,11 @@ *******************************************************************************/ package org.mitre.openid.connect.service.impl; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.isA; +import static org.mockito.Matchers.isNull; + import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; @@ -83,18 +88,12 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.isA; -import static org.mockito.Matchers.isNull; - import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.Mockito.withSettings; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @@ -1147,7 +1146,7 @@ public void testExportGrants() throws IOException, ParseException { site1.setUserId("user1"); site1.setAllowedScopes(ImmutableSet.of("openid", "phone")); when(mockToken1.getApprovedSite()).thenReturn(site1); - + Date creationDate2 = formatter.parse("2014-09-11T18:49:44.090+0000", Locale.ENGLISH); Date accessDate2 = formatter.parse("2014-09-11T20:49:44.090+0000", Locale.ENGLISH); Date timeoutDate2 = formatter.parse("2014-10-01T20:49:44.090+0000", Locale.ENGLISH); diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestUUIDPairwiseIdentiferService.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestUUIDPairwiseIdentiferService.java index ed35d82af3..734ddac3b7 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestUUIDPairwiseIdentiferService.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestUUIDPairwiseIdentiferService.java @@ -15,7 +15,7 @@ * limitations under the License. *******************************************************************************/ /** - * + * */ package org.mitre.openid.connect.service.impl; diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/util/TestIdTokenHashUtils.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/util/TestIdTokenHashUtils.java index f828135fd8..c9fec59d2b 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/util/TestIdTokenHashUtils.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/util/TestIdTokenHashUtils.java @@ -34,7 +34,7 @@ import static org.junit.Assert.assertEquals; /** - * + * * @author wkim * */ diff --git a/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsOnAnyPolicy.java b/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsOnAnyPolicy.java index 1759a8af31..1c180d5125 100644 --- a/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsOnAnyPolicy.java +++ b/uma-server/src/main/java/org/mitre/uma/service/impl/MatchAllClaimsOnAnyPolicy.java @@ -31,7 +31,7 @@ /** * Tests if all the claims in the required set have a matching * value in the supplied set. - * + * * @author jricher * */ diff --git a/uma-server/src/main/java/org/mitre/uma/service/impl/UmaDataServiceExtension_1_3.java b/uma-server/src/main/java/org/mitre/uma/service/impl/UmaDataServiceExtension_1_3.java index dc58922c34..ee7eeb09d5 100644 --- a/uma-server/src/main/java/org/mitre/uma/service/impl/UmaDataServiceExtension_1_3.java +++ b/uma-server/src/main/java/org/mitre/uma/service/impl/UmaDataServiceExtension_1_3.java @@ -59,74 +59,14 @@ */ @Service("umaDataExtension_1_3") public class UmaDataServiceExtension_1_3 extends MITREidDataServiceSupport implements MITREidDataServiceExtension { - + private static final String THIS_VERSION = MITREidDataService.MITREID_CONNECT_1_3; private static final String REGISTERED_CLIENT = "registeredClient"; - private static final String DEFAULT_SCOPE = "defaultScope"; - private static final String STRUCTURED_PARAMETER = "structuredParameter"; - private static final String STRUCTURED = "structured"; - private static final String RESTRICTED = "restricted"; - private static final String ICON = "icon"; - private static final String DYNAMICALLY_REGISTERED = "dynamicallyRegistered"; - private static final String CLEAR_ACCESS_TOKENS_ON_REFRESH = "clearAccessTokensOnRefresh"; - private static final String REUSE_REFRESH_TOKEN = "reuseRefreshToken"; - private static final String ALLOW_INTROSPECTION = "allowIntrospection"; - private static final String DESCRIPTION = "description"; - private static final String REQUEST_URIS = "requestUris"; - private static final String POST_LOGOUT_REDIRECT_URI = "postLogoutRedirectUri"; - private static final String INTITATE_LOGIN_URI = "intitateLoginUri"; - private static final String DEFAULT_ACR_VALUES = "defaultACRValues"; - private static final String REQUIRE_AUTH_TIME = "requireAuthTime"; - private static final String DEFAULT_MAX_AGE = "defaultMaxAge"; - private static final String TOKEN_ENDPOINT_AUTH_SIGNING_ALG = "tokenEndpointAuthSigningAlg"; - private static final String USER_INFO_ENCRYPTED_RESPONSE_ENC = "userInfoEncryptedResponseEnc"; - private static final String USER_INFO_ENCRYPTED_RESPONSE_ALG = "userInfoEncryptedResponseAlg"; - private static final String USER_INFO_SIGNED_RESPONSE_ALG = "userInfoSignedResponseAlg"; - private static final String ID_TOKEN_ENCRYPTED_RESPONSE_ENC = "idTokenEncryptedResponseEnc"; - private static final String ID_TOKEN_ENCRYPTED_RESPONSE_ALG = "idTokenEncryptedResponseAlg"; - private static final String ID_TOKEN_SIGNED_RESPONSE_ALG = "idTokenSignedResponseAlg"; - private static final String REQUEST_OBJECT_SIGNING_ALG = "requestObjectSigningAlg"; - private static final String SUBJECT_TYPE = "subjectType"; - private static final String SECTOR_IDENTIFIER_URI = "sectorIdentifierUri"; - private static final String APPLICATION_TYPE = "applicationType"; - private static final String JWKS = "jwks"; - private static final String JWKS_URI = "jwksUri"; - private static final String POLICY_URI = "policyUri"; - private static final String GRANT_TYPES = "grantTypes"; - private static final String TOKEN_ENDPOINT_AUTH_METHOD = "tokenEndpointAuthMethod"; - private static final String TOS_URI = "tosUri"; - private static final String CONTACTS = "contacts"; - private static final String LOGO_URI = "logoUri"; - private static final String REDIRECT_URIS = "redirectUris"; - private static final String REFRESH_TOKEN_VALIDITY_SECONDS = "refreshTokenValiditySeconds"; - private static final String ACCESS_TOKEN_VALIDITY_SECONDS = "accessTokenValiditySeconds"; - private static final String SECRET = "secret"; private static final String URI = "uri"; - private static final String CREATOR_USER_ID = "creatorUserId"; - private static final String APPROVED_ACCESS_TOKENS = "approvedAccessTokens"; - private static final String ALLOWED_SCOPES = "allowedScopes"; - private static final String USER_ID = "userId"; - private static final String TIMEOUT_DATE = "timeoutDate"; - private static final String CREATION_DATE = "creationDate"; - private static final String ACCESS_DATE = "accessDate"; - private static final String AUTHENTICATED = "authenticated"; - private static final String SOURCE_CLASS = "sourceClass"; private static final String NAME = "name"; - private static final String SAVED_USER_AUTHENTICATION = "savedUserAuthentication"; - private static final String EXTENSIONS = "extensions"; - private static final String RESPONSE_TYPES = "responseTypes"; - private static final String REDIRECT_URI = "redirectUri"; - private static final String APPROVED = "approved"; - private static final String AUTHORITIES = "authorities"; - private static final String RESOURCE_IDS = "resourceIds"; - private static final String REQUEST_PARAMETERS = "requestParameters"; private static final String TYPE = "type"; - private static final String SCOPE = "scope"; - private static final String ID_TOKEN_ID = "idTokenId"; - private static final String REFRESH_TOKEN_ID = "refreshTokenId"; private static final String VALUE = "value"; - private static final String AUTHENTICATION_HOLDER_ID = "authenticationHolderId"; private static final String CLIENT_ID = "clientId"; private static final String EXPIRATION = "expiration"; private static final String ID = "id"; @@ -153,7 +93,7 @@ public class UmaDataServiceExtension_1_3 extends MITREidDataServiceSupport imple private static final Logger logger = LoggerFactory.getLogger(UmaDataServiceExtension_1_3.class); - + @Autowired private SavedRegisteredClientService registeredClientService; @Autowired @@ -193,7 +133,7 @@ public void exportExtensionData(JsonWriter writer) throws IOException { writer.beginArray(); writePermissionTickets(writer); writer.endArray(); - + writer.name(TOKEN_PERMISSIONS); writer.beginArray(); writeTokenPermissions(writer); @@ -202,7 +142,7 @@ public void exportExtensionData(JsonWriter writer) throws IOException { /** * @param writer - * @throws IOException + * @throws IOException */ private void writeTokenPermissions(JsonWriter writer) throws IOException { for (OAuth2AccessTokenEntity token : tokenRepository.getAllAccessTokens()) { @@ -223,10 +163,10 @@ private void writeTokenPermissions(JsonWriter writer) throws IOException { writer.endObject(); } writer.endArray(); - + writer.endObject(); } - } + } } /** @@ -383,7 +323,7 @@ public boolean importExtensionData(String name, JsonReader reader) throws IOExce return false; } } - + /** * @param reader */ @@ -410,25 +350,25 @@ private void readTokenPermissions(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String pname = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (pname.equals(RESOURCE_SET)) { - rsid = reader.nextLong(); - } else if (pname.equals(SCOPES)) { - scope = readSet(reader); - } else { + case END_OBJECT: + continue; + case NAME: + String pname = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (pname.equals(RESOURCE_SET)) { + rsid = reader.nextLong(); + } else if (pname.equals(SCOPES)) { + scope = readSet(reader); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); + } + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -450,7 +390,7 @@ private void readTokenPermissions(JsonReader reader) throws IOException { tokenToPermissionRefs.put(tokenId, permissions); } reader.endArray(); - + } private Map permissionToResourceRefs = new HashMap<>(); @@ -466,99 +406,99 @@ private void readPermissionTickets(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals(CLAIMS_SUPPLIED)) { - Set claimsSupplied = new HashSet<>(); - reader.beginArray(); - while (reader.hasNext()) { - Claim c = new Claim(); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals(CLAIMS_SUPPLIED)) { + Set claimsSupplied = new HashSet<>(); + reader.beginArray(); + while (reader.hasNext()) { + Claim c = new Claim(); + reader.beginObject(); + while (reader.hasNext()) { + switch (reader.peek()) { + case END_OBJECT: + continue; + case NAME: + String cname = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (cname.equals(ISSUER)) { + c.setIssuer(readSet(reader)); + } else if (cname.equals(CLAIM_TOKEN_FORMAT)) { + c.setClaimTokenFormat(readSet(reader)); + } else if (cname.equals(CLAIM_TYPE)) { + c.setClaimType(reader.nextString()); + } else if (cname.equals(FRIENDLY_NAME)) { + c.setFriendlyName(reader.nextString()); + } else if (cname.equals(NAME)) { + c.setName(reader.nextString()); + } else if (cname.equals(VALUE)) { + JsonElement e = parser.parse(reader.nextString()); + c.setValue(e); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); + } + break; + default: + logger.debug("Found unexpected entry"); + reader.skipValue(); + continue; + } + } + reader.endObject(); + claimsSupplied.add(c); + } + reader.endArray(); + ticket.setClaimsSupplied(claimsSupplied); + } else if (name.equals(EXPIRATION)) { + ticket.setExpiration(utcToDate(reader.nextString())); + } else if (name.equals(PERMISSION)) { + Permission p = new Permission(); + Long rsid = null; reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String cname = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (cname.equals(ISSUER)) { - c.setIssuer(readSet(reader)); - } else if (cname.equals(CLAIM_TOKEN_FORMAT)) { - c.setClaimTokenFormat(readSet(reader)); - } else if (cname.equals(CLAIM_TYPE)) { - c.setClaimType(reader.nextString()); - } else if (cname.equals(FRIENDLY_NAME)) { - c.setFriendlyName(reader.nextString()); - } else if (cname.equals(NAME)) { - c.setName(reader.nextString()); - } else if (cname.equals(VALUE)) { - JsonElement e = parser.parse(reader.nextString()); - c.setValue(e); - } else { + case END_OBJECT: + continue; + case NAME: + String pname = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (pname.equals(RESOURCE_SET)) { + rsid = reader.nextLong(); + } else if (pname.equals(SCOPES)) { + p.setScopes(readSet(reader)); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); + } + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); - claimsSupplied.add(c); - } - reader.endArray(); - ticket.setClaimsSupplied(claimsSupplied); - } else if (name.equals(EXPIRATION)) { - ticket.setExpiration(utcToDate(reader.nextString())); - } else if (name.equals(PERMISSION)) { - Permission p = new Permission(); - Long rsid = null; - reader.beginObject(); - while (reader.hasNext()) { - switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String pname = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (pname.equals(RESOURCE_SET)) { - rsid = reader.nextLong(); - } else if (pname.equals(SCOPES)) { - p.setScopes(readSet(reader)); - } else { - logger.debug("Found unexpected entry"); - reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; - } + Permission saved = permissionRepository.saveRawPermission(p); + permissionToResourceRefs.put(saved.getId(), rsid); + ticket.setPermission(saved); + } else if (name.equals(TICKET)) { + ticket.setTicket(reader.nextString()); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); } - reader.endObject(); - Permission saved = permissionRepository.saveRawPermission(p); - permissionToResourceRefs.put(saved.getId(), rsid); - ticket.setPermission(saved); - } else if (name.equals(TICKET)) { - ticket.setTicket(reader.nextString()); - } else { + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -582,114 +522,114 @@ private void readResourceSets(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals(ID)) { - oldId = reader.nextLong(); - } else if (name.equals(CLIENT_ID)) { - rs.setClientId(reader.nextString()); - } else if (name.equals(ICON_URI)) { - rs.setIconUri(reader.nextString()); - } else if (name.equals(NAME)) { - rs.setName(reader.nextString()); - } else if (name.equals(TYPE)) { - rs.setType(reader.nextString()); - } else if (name.equals(URI)) { - rs.setUri(reader.nextString()); - } else if (name.equals(OWNER)) { - rs.setOwner(reader.nextString()); - } else if (name.equals(POLICIES)) { - Set policies = new HashSet<>(); - reader.beginArray(); - while (reader.hasNext()) { - Policy p = new Policy(); - reader.beginObject(); + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals(ID)) { + oldId = reader.nextLong(); + } else if (name.equals(CLIENT_ID)) { + rs.setClientId(reader.nextString()); + } else if (name.equals(ICON_URI)) { + rs.setIconUri(reader.nextString()); + } else if (name.equals(NAME)) { + rs.setName(reader.nextString()); + } else if (name.equals(TYPE)) { + rs.setType(reader.nextString()); + } else if (name.equals(URI)) { + rs.setUri(reader.nextString()); + } else if (name.equals(OWNER)) { + rs.setOwner(reader.nextString()); + } else if (name.equals(POLICIES)) { + Set policies = new HashSet<>(); + reader.beginArray(); while (reader.hasNext()) { - switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String pname = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (pname.equals(NAME)) { - p.setName(reader.nextString()); - } else if (pname.equals(SCOPES)) { - p.setScopes(readSet(reader)); - } else if (pname.equals(CLAIMS_REQUIRED)) { - Set claimsRequired = new HashSet<>(); - reader.beginArray(); - while (reader.hasNext()) { - Claim c = new Claim(); - reader.beginObject(); - while (reader.hasNext()) { - switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String cname = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (cname.equals(ISSUER)) { - c.setIssuer(readSet(reader)); - } else if (cname.equals(CLAIM_TOKEN_FORMAT)) { - c.setClaimTokenFormat(readSet(reader)); - } else if (cname.equals(CLAIM_TYPE)) { - c.setClaimType(reader.nextString()); - } else if (cname.equals(FRIENDLY_NAME)) { - c.setFriendlyName(reader.nextString()); - } else if (cname.equals(NAME)) { - c.setName(reader.nextString()); - } else if (cname.equals(VALUE)) { - JsonElement e = parser.parse(reader.nextString()); - c.setValue(e); - } else { - logger.debug("Found unexpected entry"); - reader.skipValue(); + Policy p = new Policy(); + reader.beginObject(); + while (reader.hasNext()) { + switch (reader.peek()) { + case END_OBJECT: + continue; + case NAME: + String pname = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (pname.equals(NAME)) { + p.setName(reader.nextString()); + } else if (pname.equals(SCOPES)) { + p.setScopes(readSet(reader)); + } else if (pname.equals(CLAIMS_REQUIRED)) { + Set claimsRequired = new HashSet<>(); + reader.beginArray(); + while (reader.hasNext()) { + Claim c = new Claim(); + reader.beginObject(); + while (reader.hasNext()) { + switch (reader.peek()) { + case END_OBJECT: + continue; + case NAME: + String cname = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (cname.equals(ISSUER)) { + c.setIssuer(readSet(reader)); + } else if (cname.equals(CLAIM_TOKEN_FORMAT)) { + c.setClaimTokenFormat(readSet(reader)); + } else if (cname.equals(CLAIM_TYPE)) { + c.setClaimType(reader.nextString()); + } else if (cname.equals(FRIENDLY_NAME)) { + c.setFriendlyName(reader.nextString()); + } else if (cname.equals(NAME)) { + c.setName(reader.nextString()); + } else if (cname.equals(VALUE)) { + JsonElement e = parser.parse(reader.nextString()); + c.setValue(e); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); + } + break; + default: + logger.debug("Found unexpected entry"); + reader.skipValue(); + continue; + } } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + reader.endObject(); + claimsRequired.add(c); } + reader.endArray(); + p.setClaimsRequired(claimsRequired); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); } - reader.endObject(); - claimsRequired.add(c); - } - reader.endArray(); - p.setClaimsRequired(claimsRequired); - } else { - logger.debug("Found unexpected entry"); - reader.skipValue(); + break; + default: + logger.debug("Found unexpected entry"); + reader.skipValue(); + continue; } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; } + reader.endObject(); + policies.add(p); } - reader.endObject(); - policies.add(p); + reader.endArray(); + rs.setPolicies(policies); + } else if (name.equals(SCOPES)) { + rs.setScopes(readSet(reader)); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); } - reader.endArray(); - rs.setPolicies(policies); - } else if (name.equals(SCOPES)) { - rs.setScopes(readSet(reader)); - } else { + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -711,25 +651,25 @@ private void readSavedRegisteredClients(JsonReader reader) throws IOException{ reader.beginObject(); while (reader.hasNext()) { switch (reader.peek()) { - case END_OBJECT: - continue; - case NAME: - String name = reader.nextName(); - if (reader.peek() == JsonToken.NULL) { - reader.skipValue(); - } else if (name.equals(ISSUER)) { - issuer = reader.nextString(); - } else if (name.equals(REGISTERED_CLIENT)) { - clientString = reader.nextString(); - } else { + case END_OBJECT: + continue; + case NAME: + String name = reader.nextName(); + if (reader.peek() == JsonToken.NULL) { + reader.skipValue(); + } else if (name.equals(ISSUER)) { + issuer = reader.nextString(); + } else if (name.equals(REGISTERED_CLIENT)) { + clientString = reader.nextString(); + } else { + logger.debug("Found unexpected entry"); + reader.skipValue(); + } + break; + default: logger.debug("Found unexpected entry"); reader.skipValue(); - } - break; - default: - logger.debug("Found unexpected entry"); - reader.skipValue(); - continue; + continue; } } reader.endObject(); @@ -758,13 +698,13 @@ public void fixExtensionObjectReferences(MITREidDataServiceMaps maps) { for (Long tokenId : tokenToPermissionRefs.keySet()) { Long newTokenId = maps.getAccessTokenOldToNewIdMap().get(tokenId); OAuth2AccessTokenEntity token = tokenRepository.getAccessTokenById(newTokenId); - + Set permissions = new HashSet<>(); for (Long permissionId : tokenToPermissionRefs.get(tokenId)) { Permission p = permissionRepository.getById(permissionId); permissions.add(p); } - + token.setPermissions(permissions); tokenRepository.saveAccessToken(token); } diff --git a/uma-server/src/main/java/org/mitre/uma/util/ExternalLoginAuthoritiesMapper.java b/uma-server/src/main/java/org/mitre/uma/util/ExternalLoginAuthoritiesMapper.java index cf31d41627..496a49ad56 100644 --- a/uma-server/src/main/java/org/mitre/uma/util/ExternalLoginAuthoritiesMapper.java +++ b/uma-server/src/main/java/org/mitre/uma/util/ExternalLoginAuthoritiesMapper.java @@ -30,7 +30,7 @@ /** * Utility class to map all external logins to the ROLE_EXTERNAL_USER authority * to prevent them from accessing other parts of the server. - * + * * @author jricher * */ diff --git a/uma-server/src/main/java/org/mitre/uma/view/ResourceSetEntityAbbreviatedView.java b/uma-server/src/main/java/org/mitre/uma/view/ResourceSetEntityAbbreviatedView.java index c10eb6c88e..616ea8eac6 100644 --- a/uma-server/src/main/java/org/mitre/uma/view/ResourceSetEntityAbbreviatedView.java +++ b/uma-server/src/main/java/org/mitre/uma/view/ResourceSetEntityAbbreviatedView.java @@ -56,28 +56,28 @@ public class ResourceSetEntityAbbreviatedView extends AbstractView { private ConfigurationPropertiesBean config; private Gson gson = new GsonBuilder() - .setExclusionStrategies(new ExclusionStrategy() { - - @Override - public boolean shouldSkipField(FieldAttributes f) { - - return false; - } - - @Override - public boolean shouldSkipClass(Class clazz) { - // skip the JPA binding wrapper - if (clazz.equals(BeanPropertyBindingResult.class)) { - return true; - } - return false; - } - - }) - .serializeNulls() - .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") - .setLongSerializationPolicy(LongSerializationPolicy.STRING) - .create(); + .setExclusionStrategies(new ExclusionStrategy() { + + @Override + public boolean shouldSkipField(FieldAttributes f) { + + return false; + } + + @Override + public boolean shouldSkipClass(Class clazz) { + // skip the JPA binding wrapper + if (clazz.equals(BeanPropertyBindingResult.class)) { + return true; + } + return false; + } + + }) + .serializeNulls() + .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") + .setLongSerializationPolicy(LongSerializationPolicy.STRING) + .create(); @Override protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) { diff --git a/uma-server/src/main/java/org/mitre/uma/view/ResourceSetEntityView.java b/uma-server/src/main/java/org/mitre/uma/view/ResourceSetEntityView.java index 2d50cdee40..bd9a558735 100644 --- a/uma-server/src/main/java/org/mitre/uma/view/ResourceSetEntityView.java +++ b/uma-server/src/main/java/org/mitre/uma/view/ResourceSetEntityView.java @@ -54,28 +54,28 @@ public class ResourceSetEntityView extends AbstractView { private ConfigurationPropertiesBean config; private Gson gson = new GsonBuilder() - .setExclusionStrategies(new ExclusionStrategy() { - - @Override - public boolean shouldSkipField(FieldAttributes f) { - - return false; - } - - @Override - public boolean shouldSkipClass(Class clazz) { - // skip the JPA binding wrapper - if (clazz.equals(BeanPropertyBindingResult.class)) { - return true; - } - return false; - } - - }) - .serializeNulls() - .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") - .setLongSerializationPolicy(LongSerializationPolicy.STRING) - .create(); + .setExclusionStrategies(new ExclusionStrategy() { + + @Override + public boolean shouldSkipField(FieldAttributes f) { + + return false; + } + + @Override + public boolean shouldSkipClass(Class clazz) { + // skip the JPA binding wrapper + if (clazz.equals(BeanPropertyBindingResult.class)) { + return true; + } + return false; + } + + }) + .serializeNulls() + .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") + .setLongSerializationPolicy(LongSerializationPolicy.STRING) + .create(); @Override protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) { diff --git a/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java index 67af05c070..79fe62b8eb 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/AuthorizationRequestEndpoint.java @@ -23,7 +23,6 @@ import org.mitre.oauth2.service.OAuth2TokenEntityService; import org.mitre.oauth2.service.SystemScopeService; import org.mitre.oauth2.web.AuthenticationUtilities; -import org.mitre.openid.connect.service.OIDCTokenService; import org.mitre.openid.connect.view.HttpCodeView; import org.mitre.openid.connect.view.JsonEntityView; import org.mitre.openid.connect.view.JsonErrorView; @@ -74,9 +73,6 @@ public class AuthorizationRequestEndpoint { @Autowired private OAuth2TokenEntityService tokenService; - @Autowired - private OIDCTokenService oidcTokenService; - @Autowired private ClaimsProcessingService claimsProcessingService; diff --git a/uma-server/src/main/java/org/mitre/uma/web/ClaimsCollectionEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/ClaimsCollectionEndpoint.java index d281a51d2b..7cc8c1e8f6 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/ClaimsCollectionEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/ClaimsCollectionEndpoint.java @@ -46,9 +46,9 @@ import com.google.gson.JsonPrimitive; /** - * + * * Collect claims interactively from the end user. - * + * * @author jricher * */ diff --git a/uma-server/src/main/java/org/mitre/uma/web/PermissionRegistrationEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/PermissionRegistrationEndpoint.java index e4374f0b7a..f048656aff 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/PermissionRegistrationEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/PermissionRegistrationEndpoint.java @@ -17,6 +17,10 @@ package org.mitre.uma.web; +import static org.mitre.oauth2.web.AuthenticationUtilities.ensureOAuthScope; +import static org.mitre.util.JsonUtils.getAsLong; +import static org.mitre.util.JsonUtils.getAsStringSet; + import java.util.Set; import org.mitre.oauth2.model.SystemScope; @@ -45,10 +49,6 @@ import com.google.gson.JsonParseException; import com.google.gson.JsonParser; -import static org.mitre.oauth2.web.AuthenticationUtilities.ensureOAuthScope; -import static org.mitre.util.JsonUtils.getAsLong; -import static org.mitre.util.JsonUtils.getAsStringSet; - /** * @author jricher * diff --git a/uma-server/src/main/java/org/mitre/uma/web/PolicyAPI.java b/uma-server/src/main/java/org/mitre/uma/web/PolicyAPI.java index a33b133928..6b25b02df8 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/PolicyAPI.java +++ b/uma-server/src/main/java/org/mitre/uma/web/PolicyAPI.java @@ -48,7 +48,7 @@ /** * API for managing policies on resource sets. - * + * * @author jricher * */ diff --git a/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java b/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java index 6e1d49bb98..5bbaa7705d 100644 --- a/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java +++ b/uma-server/src/main/java/org/mitre/uma/web/ResourceSetRegistrationEndpoint.java @@ -17,6 +17,11 @@ package org.mitre.uma.web; +import static org.mitre.oauth2.web.AuthenticationUtilities.ensureOAuthScope; +import static org.mitre.util.JsonUtils.getAsLong; +import static org.mitre.util.JsonUtils.getAsString; +import static org.mitre.util.JsonUtils.getAsStringSet; + import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -53,11 +58,6 @@ import com.google.gson.JsonParseException; import com.google.gson.JsonParser; -import static org.mitre.oauth2.web.AuthenticationUtilities.ensureOAuthScope; -import static org.mitre.util.JsonUtils.getAsLong; -import static org.mitre.util.JsonUtils.getAsString; -import static org.mitre.util.JsonUtils.getAsStringSet; - @Controller @RequestMapping("/" + ResourceSetRegistrationEndpoint.URL) @PreAuthorize("hasRole('ROLE_USER')") @@ -298,9 +298,9 @@ private ResourceSet parseResourceSet(String jsonString) { /** - * + * * Make sure the resource set doesn't have any restricted or reserved scopes. - * + * * @param rs */ private ResourceSet validateScopes(ResourceSet rs) { diff --git a/uma-server/src/test/java/org/mitre/uma/service/impl/TestDefaultPermissionService.java b/uma-server/src/test/java/org/mitre/uma/service/impl/TestDefaultPermissionService.java index 90763ae611..34c448c63f 100644 --- a/uma-server/src/test/java/org/mitre/uma/service/impl/TestDefaultPermissionService.java +++ b/uma-server/src/test/java/org/mitre/uma/service/impl/TestDefaultPermissionService.java @@ -17,6 +17,8 @@ package org.mitre.uma.service.impl; +import static org.mockito.Matchers.anySetOf; + import java.util.Set; import java.util.UUID; @@ -41,8 +43,6 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.not; -import static org.mockito.Matchers.anySetOf; - import static org.mockito.Mockito.when; import static org.junit.Assert.assertNotNull; diff --git a/uma-server/src/test/java/org/mitre/uma/service/impl/TestDefaultResourceSetService.java b/uma-server/src/test/java/org/mitre/uma/service/impl/TestDefaultResourceSetService.java index a8de434c17..f8865129ec 100644 --- a/uma-server/src/test/java/org/mitre/uma/service/impl/TestDefaultResourceSetService.java +++ b/uma-server/src/test/java/org/mitre/uma/service/impl/TestDefaultResourceSetService.java @@ -17,6 +17,8 @@ package org.mitre.uma.service.impl; +import static org.mockito.Matchers.any; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -27,8 +29,6 @@ import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; -import static org.mockito.Matchers.any; - import static org.mockito.Mockito.when; /** From bd72b4138d974c383efb1460087d15832047412e Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 21 Mar 2017 14:11:40 -0400 Subject: [PATCH 368/465] added missing copyright declarations --- .../client/AuthorizationEndpointException.java | 16 ++++++++++++++++ .../client/TestOIDCAuthenticationFilter.java | 16 ++++++++++++++++ .../data/AbstractPageOperationTemplate.java | 16 ++++++++++++++++ .../org/mitre/data/DefaultPageCriteria.java | 16 ++++++++++++++++ .../main/java/org/mitre/data/PageCriteria.java | 16 ++++++++++++++++ .../data/AbstractPageOperationTemplateTest.java | 16 ++++++++++++++++ .../db/oracle/entity-mappings_oracle.xml | 16 ++++++++++++++++ .../src/main/webapp/WEB-INF/locale-config.xml | 17 +++++++++++++++++ .../src/main/webapp/WEB-INF/wro.properties | 16 ++++++++++++++++ .../src/main/webapp/WEB-INF/wro.xml | 16 ++++++++++++++++ .../src/main/webapp/resources/js/profile.js | 16 ++++++++++++++++ 11 files changed, 177 insertions(+) diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/AuthorizationEndpointException.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/AuthorizationEndpointException.java index 23b5773f5d..9e0226227f 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/AuthorizationEndpointException.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/AuthorizationEndpointException.java @@ -1,3 +1,19 @@ +/******************************************************************************* + * Copyright 2017 The MITRE Corporation + * and the MIT Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ package org.mitre.openid.connect.client; import org.springframework.security.authentication.AuthenticationServiceException; diff --git a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/TestOIDCAuthenticationFilter.java b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/TestOIDCAuthenticationFilter.java index 46ae7397f1..11563a1a81 100644 --- a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/TestOIDCAuthenticationFilter.java +++ b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/TestOIDCAuthenticationFilter.java @@ -1,3 +1,19 @@ +/******************************************************************************* + * Copyright 2017 The MITRE Corporation + * and the MIT Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ package org.mitre.openid.connect.client; import javax.servlet.http.HttpServletRequest; diff --git a/openid-connect-common/src/main/java/org/mitre/data/AbstractPageOperationTemplate.java b/openid-connect-common/src/main/java/org/mitre/data/AbstractPageOperationTemplate.java index 7911f2f029..fb7672bc5b 100644 --- a/openid-connect-common/src/main/java/org/mitre/data/AbstractPageOperationTemplate.java +++ b/openid-connect-common/src/main/java/org/mitre/data/AbstractPageOperationTemplate.java @@ -1,3 +1,19 @@ +/******************************************************************************* + * Copyright 2017 The MITRE Corporation + * and the MIT Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ package org.mitre.data; import java.util.Collection; diff --git a/openid-connect-common/src/main/java/org/mitre/data/DefaultPageCriteria.java b/openid-connect-common/src/main/java/org/mitre/data/DefaultPageCriteria.java index 5b0f659bb2..911a92f5f3 100644 --- a/openid-connect-common/src/main/java/org/mitre/data/DefaultPageCriteria.java +++ b/openid-connect-common/src/main/java/org/mitre/data/DefaultPageCriteria.java @@ -1,3 +1,19 @@ +/******************************************************************************* + * Copyright 2017 The MITRE Corporation + * and the MIT Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ package org.mitre.data; /** diff --git a/openid-connect-common/src/main/java/org/mitre/data/PageCriteria.java b/openid-connect-common/src/main/java/org/mitre/data/PageCriteria.java index 0c462434ab..5f822440ab 100644 --- a/openid-connect-common/src/main/java/org/mitre/data/PageCriteria.java +++ b/openid-connect-common/src/main/java/org/mitre/data/PageCriteria.java @@ -1,3 +1,19 @@ +/******************************************************************************* + * Copyright 2017 The MITRE Corporation + * and the MIT Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ package org.mitre.data; /** diff --git a/openid-connect-common/src/test/java/org/mitre/data/AbstractPageOperationTemplateTest.java b/openid-connect-common/src/test/java/org/mitre/data/AbstractPageOperationTemplateTest.java index 9bc11020fd..1859b9a82f 100644 --- a/openid-connect-common/src/test/java/org/mitre/data/AbstractPageOperationTemplateTest.java +++ b/openid-connect-common/src/test/java/org/mitre/data/AbstractPageOperationTemplateTest.java @@ -1,3 +1,19 @@ +/******************************************************************************* + * Copyright 2017 The MITRE Corporation + * and the MIT Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ package org.mitre.data; import java.util.ArrayList; diff --git a/openid-connect-server-webapp/src/main/resources/db/oracle/entity-mappings_oracle.xml b/openid-connect-server-webapp/src/main/resources/db/oracle/entity-mappings_oracle.xml index b1b074ac8b..4920918fb7 100644 --- a/openid-connect-server-webapp/src/main/resources/db/oracle/entity-mappings_oracle.xml +++ b/openid-connect-server-webapp/src/main/resources/db/oracle/entity-mappings_oracle.xml @@ -1,3 +1,19 @@ + + + diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/wro.properties b/openid-connect-server-webapp/src/main/webapp/WEB-INF/wro.properties index 8b8c9dd890..3940bd137c 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/wro.properties +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/wro.properties @@ -1,2 +1,18 @@ +############################################################################### +# Copyright 2017 The MITRE Corporation +# and the MIT Internet Trust Consortium +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################### preProcessors=cssImport postProcessors=lessCss diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/wro.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/wro.xml index fdd66a0b40..3d5a6c17e0 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/wro.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/wro.xml @@ -1,3 +1,19 @@ + /less/bootstrap.less diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/profile.js b/openid-connect-server-webapp/src/main/webapp/resources/js/profile.js index 4945ac711d..e9fd39ffe2 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/profile.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/profile.js @@ -1,3 +1,19 @@ +/******************************************************************************* + * Copyright 2017 The MITRE Corporation + * and the MIT Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ ui.routes.push({path: "user/profile", name: "profile", callback: function() { From 78b9b6ced4b64208b314f16e86567520ff0f1cdc Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 21 Mar 2017 15:04:18 -0400 Subject: [PATCH 369/465] auto format and cleanup javascript --- .../src/main/webapp/resources/js/admin.js | 818 ++--- .../src/main/webapp/resources/js/blacklist.js | 274 +- .../src/main/webapp/resources/js/client.js | 2618 +++++++++-------- .../src/main/webapp/resources/js/dynreg.js | 1363 +++++---- .../src/main/webapp/resources/js/grant.js | 313 +- .../src/main/webapp/resources/js/profile.js | 39 +- .../src/main/webapp/resources/js/rsreg.js | 929 +++--- .../src/main/webapp/resources/js/scope.js | 643 ++-- .../src/main/webapp/resources/js/token.js | 738 ++--- .../src/main/webapp/resources/js/whitelist.js | 759 ++--- 10 files changed, 4554 insertions(+), 3940 deletions(-) diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/admin.js b/openid-connect-server-webapp/src/main/webapp/resources/js/admin.js index fdbacdfbb0..18c2efeec1 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/admin.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/admin.js @@ -53,344 +53,386 @@ Backbone.Collection.prototype.fetchIfNeeded = function(options) { } }; -var URIModel = Backbone.Model.extend({ +var URIModel = Backbone.Model + .extend({ - validate: function(attrs){ + validate: function(attrs) { - var expression = /^(?:([a-z0-9+.-]+:\/\/)((?:(?:[a-z0-9-._~!$&'()*+,;=:]|%[0-9A-F]{2})*)@)?((?:[a-z0-9-._~!$&'()*+,;=]|%[0-9A-F]{2})*)(:(?:\d*))?(\/(?:[a-z0-9-._~!$&'()*+,;=:@\/]|%[0-9A-F]{2})*)?|([a-z0-9+.-]+:)(\/?(?:[a-z0-9-._~!$&'()*+,;=:@]|%[0-9A-F]{2})+(?:[a-z0-9-._~!$&'()*+,;=:@\/]|%[0-9A-F]{2})*)?)(\?(?:[a-z0-9-._~!$&'()*+,;=:\/?@]|%[0-9A-F]{2})*)?(#(?:[a-z0-9-._~!$&'()*+,;=:\/?@]|%[0-9A-F]{2})*)?$/i; - var regex = new RegExp(expression); + var expression = /^(?:([a-z0-9+.-]+:\/\/)((?:(?:[a-z0-9-._~!$&'()*+,;=:]|%[0-9A-F]{2})*)@)?((?:[a-z0-9-._~!$&'()*+,;=]|%[0-9A-F]{2})*)(:(?:\d*))?(\/(?:[a-z0-9-._~!$&'()*+,;=:@\/]|%[0-9A-F]{2})*)?|([a-z0-9+.-]+:)(\/?(?:[a-z0-9-._~!$&'()*+,;=:@]|%[0-9A-F]{2})+(?:[a-z0-9-._~!$&'()*+,;=:@\/]|%[0-9A-F]{2})*)?)(\?(?:[a-z0-9-._~!$&'()*+,;=:\/?@]|%[0-9A-F]{2})*)?(#(?:[a-z0-9-._~!$&'()*+,;=:\/?@]|%[0-9A-F]{2})*)?$/i; + var regex = new RegExp(expression); - if (attrs.item == null || !attrs.item.match(regex)) { - return "Invalid URI"; - } - } - -}); + if (attrs.item == null || !attrs.item.match(regex)) { + return "Invalid URI"; + } + } + }); /* -* Backbone JS Reusable ListWidget -* Options -* { -* collection: Backbone JS Collection -* type: ('uri'|'default') -* autocomplete: ['item1','item2'] List of auto complete items -* } -* + * Backbone JS Reusable ListWidget Options { collection: Backbone JS Collection + * type: ('uri'|'default') autocomplete: ['item1','item2'] List of auto complete + * items } + * */ var ListWidgetChildView = Backbone.View.extend({ - tagName: 'tr', - - events:{ - "click .btn-delete-list-item":'deleteItem', - "change .checkbox-list-item":'toggleCheckbox' - }, - - deleteItem:function (e) { - e.preventDefault(); - e.stopImmediatePropagation(); - //this.$el.tooltip('delete'); - - this.model.destroy({ - dataType: false, processData: false, - error:app.errorHandlerView.handleError() - }); - - }, - - toggleCheckbox:function(e) { - e.preventDefault(); - e.stopImmediatePropagation(); - if ($(e.target).is(':checked')) { - this.options.collection.add(this.model); - } else { - this.options.collection.remove(this.model); - } - - }, - - initialize:function (options) { - this.options = {toggle: false, checked: false}; - _.extend(this.options, options); - if (!this.template) { - this.template = _.template($('#tmpl-list-widget-child').html()); - } - }, - - render:function () { - - var data = {model: this.model.toJSON(), opt: this.options}; - - this.$el.html(this.template(data)); - - $('.item-full', this.el).hide(); - - if (this.model.get('item').length > 30) { - this.$el.tooltip({title:$.t('admin.list-widget.tooltip')}); - - var _self = this; - - $(this.el).click(function(event) { - event.preventDefault(); - $('.item-short', _self.el).hide(); - $('.item-full', _self.el).show(); - _self.$el.tooltip('destroy'); - }); - } - - - - $(this.el).i18n(); - return this; - } + tagName: 'tr', + + events: { + "click .btn-delete-list-item": 'deleteItem', + "change .checkbox-list-item": 'toggleCheckbox' + }, + + deleteItem: function(e) { + e.preventDefault(); + e.stopImmediatePropagation(); + // this.$el.tooltip('delete'); + + this.model.destroy({ + dataType: false, + processData: false, + error: app.errorHandlerView.handleError() + }); + + }, + + toggleCheckbox: function(e) { + e.preventDefault(); + e.stopImmediatePropagation(); + if ($(e.target).is(':checked')) { + this.options.collection.add(this.model); + } else { + this.options.collection.remove(this.model); + } + + }, + + initialize: function(options) { + this.options = { + toggle: false, + checked: false + }; + _.extend(this.options, options); + if (!this.template) { + this.template = _.template($('#tmpl-list-widget-child').html()); + } + }, + + render: function() { + + var data = { + model: this.model.toJSON(), + opt: this.options + }; + + this.$el.html(this.template(data)); + + $('.item-full', this.el).hide(); + + if (this.model.get('item').length > 30) { + this.$el.tooltip({ + title: $.t('admin.list-widget.tooltip') + }); + + var _self = this; + + $(this.el).click(function(event) { + event.preventDefault(); + $('.item-short', _self.el).hide(); + $('.item-full', _self.el).show(); + _self.$el.tooltip('destroy'); + }); + } + + $(this.el).i18n(); + return this; + } }); var ListWidgetView = Backbone.View.extend({ - tagName: "div", - - events:{ - "click .btn-add-list-item":"addItem", - "keypress":function (e) { - // trap the enter key - if (e.which == 13) { - e.preventDefault(); - this.addItem(e); - $("input", this.$el).focus(); - } - } - }, - - initialize:function (options) { - this.options = options; - - if (!this.template) { - this.template = _.template($('#tmpl-list-widget').html()); - } - - this.collection.bind('add', this.render, this); - this.collection.bind('remove', this.render, this); - }, - - addItem:function(e) { - e.preventDefault(); - - var input_value = $("input", this.el).val().trim(); - - if (input_value === ""){ - return; - } - - var model; - - if (this.options.type == 'uri') { - model = new URIModel({item:input_value}); - } else { - model = new Backbone.Model({item:input_value}); - model.validate = function(attrs) { - if(!attrs.item) { - return "value can't be null"; - } - }; - } - - // if it's valid and doesn't already exist - if (model.get("item") != null && this.collection.where({item: input_value}).length < 1) { - this.collection.add(model); - } else { - // else add a visual error indicator - $(".control-group", this.el).addClass('error'); - } - }, - - render:function (eventName) { - - this.$el.html(this.template({placeholder:this.options.placeholder, - helpBlockText:this.options.helpBlockText})); - - var _self = this; - - if (_.size(this.collection.models) == 0 && _.size(this.options.autocomplete) == 0) { - $("tbody", _self.el).html($('#tmpl-list-widget-child-empty').html()); - } else { - - // make a copy of our collection to work from - var values = this.collection.clone(); - - // look through our autocomplete values (if we have them) and render them all as checkboxes - if (this.options.autocomplete) { - _.each(this.options.autocomplete, function(option) { - var found = _.find(values.models, function(element) { - return element.get('item') == option; - }); - - var model = null; - var checked = false; - - if (found) { - // if we found the element, check the box - model = found; - checked = true; - // and remove it from the list of items to be rendered later - values.remove(found, {silent: true}); - } else { - model = new Backbone.Model({item:option}); - checked = false; - } - - var el = new ListWidgetChildView({model:model, toggle: true, checked: checked, collection: _self.collection}).render().el; - $("tbody", _self.el).append(el); - - }, this); - } - - - // now render everything not in the autocomplete list - _.each(values.models, function (model) { - var el = new ListWidgetChildView({model:model, collection: _self.collection}).render().el; - $("tbody", _self.el).append(el); - }, this); - } - - $(this.el).i18n(); - return this; - } - -}); + tagName: "div", -var BreadCrumbView = Backbone.View.extend({ + events: { + "click .btn-add-list-item": "addItem", + "keypress": function(e) { + // trap the enter key + if (e.which == 13) { + e.preventDefault(); + this.addItem(e); + $("input", this.$el).focus(); + } + } + }, + + initialize: function(options) { + this.options = options; + + if (!this.template) { + this.template = _.template($('#tmpl-list-widget').html()); + } + + this.collection.bind('add', this.render, this); + this.collection.bind('remove', this.render, this); + }, + + addItem: function(e) { + e.preventDefault(); - tagName: 'ul', + var input_value = $("input", this.el).val().trim(); - initialize:function (options) { - this.options = options; + if (input_value === "") { + return; + } - if (!this.template) { - this.template = _.template($('#tmpl-breadcrumbs').html()); - } + var model; + + if (this.options.type == 'uri') { + model = new URIModel({ + item: input_value + }); + } else { + model = new Backbone.Model({ + item: input_value + }); + model.validate = function(attrs) { + if (!attrs.item) { + return "value can't be null"; + } + }; + } - this.$el.addClass('breadcrumb'); + // if it's valid and doesn't already exist + if (model.get("item") != null && this.collection.where({ + item: input_value + }).length < 1) { + this.collection.add(model); + } else { + // else add a visual error indicator + $(".control-group", this.el).addClass('error'); + } + }, - this.collection.bind('add', this.render, this); - }, + render: function(eventName) { - render:function () { + this.$el.html(this.template({ + placeholder: this.options.placeholder, + helpBlockText: this.options.helpBlockText + })); - this.$el.empty(); - var parent = this; + var _self = this; - // go through each of the breadcrumb models - _.each(this.collection.models, function (crumb, index) { + if (_.size(this.collection.models) == 0 && _.size(this.options.autocomplete) == 0) { + $("tbody", _self.el).html($('#tmpl-list-widget-child-empty').html()); + } else { + + // make a copy of our collection to work from + var values = this.collection.clone(); + + // look through our autocomplete values (if we have them) and render + // them all as checkboxes + if (this.options.autocomplete) { + _.each(this.options.autocomplete, function(option) { + var found = _.find(values.models, function(element) { + return element.get('item') == option; + }); + + var model = null; + var checked = false; + + if (found) { + // if we found the element, check the box + model = found; + checked = true; + // and remove it from the list of items to be rendered + // later + values.remove(found, { + silent: true + }); + } else { + model = new Backbone.Model({ + item: option + }); + checked = false; + } + + var el = new ListWidgetChildView({ + model: model, + toggle: true, + checked: checked, + collection: _self.collection + }).render().el; + $("tbody", _self.el).append(el); + + }, this); + } - // if it's the last index in the crumbs then render the link inactive - if (index == parent.collection.size() - 1) { - crumb.set({active:true}, {silent:true}); - } else { - crumb.set({active:false}, {silent:true}); - } + // now render everything not in the autocomplete list + _.each(values.models, function(model) { + var el = new ListWidgetChildView({ + model: model, + collection: _self.collection + }).render().el; + $("tbody", _self.el).append(el); + }, this); + } - this.$el.append(this.template(crumb.toJSON())); - }, this); + $(this.el).i18n(); + return this; + } - $('#breadcrumbs').html(this.el); - $(this.el).i18n(); - } }); +var BreadCrumbView = Backbone.View.extend({ + + tagName: 'ul', + + initialize: function(options) { + this.options = options; + + if (!this.template) { + this.template = _.template($('#tmpl-breadcrumbs').html()); + } + + this.$el.addClass('breadcrumb'); + + this.collection.bind('add', this.render, this); + }, + + render: function() { + + this.$el.empty(); + var parent = this; + + // go through each of the breadcrumb models + _.each(this.collection.models, function(crumb, index) { + + // if it's the last index in the crumbs then render the link + // inactive + if (index == parent.collection.size() - 1) { + crumb.set({ + active: true + }, { + silent: true + }); + } else { + crumb.set({ + active: false + }, { + silent: true + }); + } + + this.$el.append(this.template(crumb.toJSON())); + }, this); + + $('#breadcrumbs').html(this.el); + $(this.el).i18n(); + } +}); // User Profile var UserProfileView = Backbone.View.extend({ tagName: 'span', - - initialize:function(options) { - this.options = options; - if (!this.template) { - this.template = _.template($('#tmpl-user-profile-element').html()); - } + + initialize: function(options) { + this.options = options; + if (!this.template) { + this.template = _.template($('#tmpl-user-profile-element').html()); + } }, - - render:function() { - - $(this.el).html($('#tmpl-user-profile').html()); - - var t = this.template; - - _.each(this.model, function (value, key) { - if (key && value) { - - if (typeof(value) === 'object') { - - var el = this.el; - var k = key; - - _.each(value, function (value, key) { - $('dl', el).append( - t({key: key, value: value, category: k}) - ); - }); - } else if (typeof(value) === 'array') { - // TODO: handle array types - } else { - $('dl', this.el).append( - t({key: key, value: value}) - ); - } - } - }, this); - - $(this.el).i18n(); + + render: function() { + + $(this.el).html($('#tmpl-user-profile').html()); + + var t = this.template; + + _.each(this.model, function(value, key) { + if (key && value) { + + if (typeof (value) === 'object') { + + var el = this.el; + var k = key; + + _.each(value, function(value, key) { + $('dl', el).append(t({ + key: key, + value: value, + category: k + })); + }); + } else if (typeof (value) === 'array') { + // TODO: handle array types + } else { + $('dl', this.el).append(t({ + key: key, + value: value + })); + } + } + }, this); + + $(this.el).i18n(); return this; } }); // error handler var ErrorHandlerView = Backbone.View.extend({ - - initialize:function(options) { - this.options = options; - if (!this.template) { - this.template = _.template($('#tmpl-error-box').html()); - } - if (!this.headerTemplate) { - this.headerTemplate = _.template($('#tmpl-error-header').html()); - } + + initialize: function(options) { + this.options = options; + if (!this.template) { + this.template = _.template($('#tmpl-error-box').html()); + } + if (!this.headerTemplate) { + this.headerTemplate = _.template($('#tmpl-error-header').html()); + } }, - - reloadPage:function(event) { + + reloadPage: function(event) { event.preventDefault(); window.location.reload(true); }, - handleError:function(message) { - + handleError: function(message) { + if (!message) { message = {}; } var _self = this; - + return function(model, response, options) { - + if (message.log) { console.log(message.log); } - - _self.showErrorMessage( - _self.headerTemplate({message: message, model: model, response: response, options: options}), - _self.template({message: message, model: model, response: response, options: options}) - ); - + + _self.showErrorMessage(_self.headerTemplate({ + message: message, + model: model, + response: response, + options: options + }), _self.template({ + message: message, + model: model, + response: response, + options: options + })); + $('#modalAlert .modal-body .page-reload').on('click', _self.reloadPage); } - }, - - showErrorMessage:function(header, message) { + }, + + showErrorMessage: function(header, message) { // hide the sheet if it's visible $('#loadingbox').sheet('hide'); - + $('#modalAlert').i18n(); $('#modalAlert div.modal-header').html(header); $('#modalAlert .modal-body').html(message); @@ -400,62 +442,66 @@ var ErrorHandlerView = Backbone.View.extend({ 'keyboard': true, 'show': true }); - + } }); - // Router var AppRouter = Backbone.Router.extend({ - routes:{ - - "": "root" - - }, - - root:function() { - if (isAdmin()) { - this.navigate('admin/clients', {trigger: true}); - } else { - this.navigate('user/approved', {trigger: true}); - } - }, - - initialize:function () { - - this.breadCrumbView = new BreadCrumbView({ - collection:new Backbone.Collection() - }); - - this.breadCrumbView.render(); - - this.errorHandlerView = new ErrorHandlerView(); - - // call all the extra initialization functions - var app = this; - _.each(ui.init, function(fn) { - fn(app); - }); - - }, - - notImplemented:function(){ - this.breadCrumbView.collection.reset(); - this.breadCrumbView.collection.add([ - {text:$.t('admin.home'), href:""} - ]); - - this.updateSidebar('none'); - - $('#content').html("

Not implemented yet.

"); - }, - - updateSidebar:function(item) { - $('.sidebar-nav li.active').removeClass('active'); - - $('.sidebar-nav li a[href^="manage/#' + item + '"]').parent().addClass('active'); - } + routes: { + + "": "root" + + }, + + root: function() { + if (isAdmin()) { + this.navigate('admin/clients', { + trigger: true + }); + } else { + this.navigate('user/approved', { + trigger: true + }); + } + }, + + initialize: function() { + + this.breadCrumbView = new BreadCrumbView({ + collection: new Backbone.Collection() + }); + + this.breadCrumbView.render(); + + this.errorHandlerView = new ErrorHandlerView(); + + // call all the extra initialization functions + var app = this; + _.each(ui.init, function(fn) { + fn(app); + }); + + }, + + notImplemented: function() { + this.breadCrumbView.collection.reset(); + this.breadCrumbView.collection.add([{ + text: $.t('admin.home'), + href: "" + }]); + + this.updateSidebar('none'); + + $('#content').html("

Not implemented yet.

"); + }, + + updateSidebar: function(item) { + $('.sidebar-nav li.active').removeClass('active'); + + $('.sidebar-nav li a[href^="manage/#' + item + '"]').parent().addClass('active'); + } }); // holds the global app. @@ -463,59 +509,67 @@ var AppRouter = Backbone.Router.extend({ var app = null; // main -$(function () { - - var loader = function(source) { - return $.get(source, function (templates) { - console.log('Loading file: ' + source); - $('#templates').append(templates); - }); - }; - - // load templates and append them to the body - $.when.apply(null, ui.templates.map(loader) - ).done(function() { - console.log('done'); - $.ajaxSetup({cache:false}); - app = new AppRouter(); - - _.each(ui.routes.reverse(), function(route) { - console.log("Adding route: " + route.name); - app.route(route.path, route.name, route.callback); - }); - - app.on('route', function(name, args) { - // scroll to top of page on new route selection - $("html, body").animate({ scrollTop: 0 }, "slow"); - }); - - // grab all hashed URLs and send them through the app router instead - $(document).on('click', 'a[href^="manage/#"]', function(event) { - event.preventDefault(); - app.navigate(this.hash.slice(1), {trigger: true}); - }); - - var base = $('base').attr('href'); - $.getJSON(base + '.well-known/openid-configuration', function(data) { - app.serverConfiguration = data; - var baseUrl = $.url(app.serverConfiguration.issuer); - Backbone.history.start({pushState: true, root: baseUrl.attr('relative') + 'manage/'}); - }); - }); - - window.onerror = function ( message, filename, lineno, colno, error ){ - console.log(message); - //Display an alert with an error message +$(function() { + + var loader = function(source) { + return $.get(source, function(templates) { + console.log('Loading file: ' + source); + $('#templates').append(templates); + }); + }; + + // load templates and append them to the body + $.when.apply(null, ui.templates.map(loader)).done(function() { + console.log('done'); + $.ajaxSetup({ + cache: false + }); + app = new AppRouter(); + + _.each(ui.routes.reverse(), function(route) { + console.log("Adding route: " + route.name); + app.route(route.path, route.name, route.callback); + }); + + app.on('route', function(name, args) { + // scroll to top of page on new route selection + $("html, body").animate({ + scrollTop: 0 + }, "slow"); + }); + + // grab all hashed URLs and send them through the app router instead + $(document).on('click', 'a[href^="manage/#"]', function(event) { + event.preventDefault(); + app.navigate(this.hash.slice(1), { + trigger: true + }); + }); + + var base = $('base').attr('href'); + $.getJSON(base + '.well-known/openid-configuration', function(data) { + app.serverConfiguration = data; + var baseUrl = $.url(app.serverConfiguration.issuer); + Backbone.history.start({ + pushState: true, + root: baseUrl.attr('relative') + 'manage/' + }); + }); + }); + + window.onerror = function(message, filename, lineno, colno, error) { + console.log(message); + // Display an alert with an error message $('#modalAlert div.modal-header').html($.t('error.title')); $('#modalAlert div.modal-body').html($.t('error.message') + message + '
' + [filename, lineno, colno, error]); - - $("#modalAlert").modal({ // wire up the actual modal functionality and show the dialog - "backdrop" : "static", - "keyboard" : true, - "show" : true // ensure the modal is shown immediately - }); - - } -}); + $("#modalAlert").modal({ // wire up the actual modal functionality + // and show the dialog + "backdrop": "static", + "keyboard": true, + "show": true + // ensure the modal is shown immediately + }); + } +}); diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/blacklist.js b/openid-connect-server-webapp/src/main/webapp/resources/js/blacklist.js index 719a685172..7b14046990 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/blacklist.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/blacklist.js @@ -16,63 +16,64 @@ *******************************************************************************/ var BlackListModel = Backbone.Model.extend({ idAttribute: 'id', - + urlRoot: 'api/blacklist' }); var BlackListCollection = Backbone.Collection.extend({ - initialize: function() { }, + initialize: function() { + }, url: "api/blacklist" }); var BlackListListView = Backbone.View.extend({ tagName: 'span', - - initialize:function(options) { - this.options = options; + + initialize: function(options) { + this.options = options; + }, + + load: function(callback) { + if (this.collection.isFetched) { + callback(); + return; + } + + $('#loadingbox').sheet('show'); + $('#loading').html('' + $.t('admin.blacklist') + ' '); + + $.when(this.collection.fetchIfNeeded({ + success: function(e) { + $('#loading-blacklist').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + })).done(function() { + $('#loadingbox').sheet('hide'); + callback(); + }); }, - load:function(callback) { - if (this.collection.isFetched) { - callback(); - return; - } - - $('#loadingbox').sheet('show'); - $('#loading').html( - '' + $.t('admin.blacklist') + ' ' - ); - - $.when(this.collection.fetchIfNeeded({success:function(e) {$('#loading-blacklist').addClass('label-success');}, error:app.errorHandlerView.handleError()})) - .done(function() { - $('#loadingbox').sheet('hide'); - callback(); - }); - }, - events: { - "click .refresh-table":"refreshTable", - "click .btn-add":"addItem", - "submit #add-blacklist form":"addItem" + "click .refresh-table": "refreshTable", + "click .btn-add": "addItem", + "submit #add-blacklist form": "addItem" }, - refreshTable:function(e) { - e.preventDefault(); - - var _self = this; - $('#loadingbox').sheet('show'); - $('#loading').html( - '' + $.t('admin.blacklist') + ' ' - ); - - $.when(this.collection.fetch()).done(function() { - $('#loadingbox').sheet('hide'); - _self.render(); - }); - }, - - togglePlaceholder:function() { + refreshTable: function(e) { + e.preventDefault(); + + var _self = this; + $('#loadingbox').sheet('show'); + $('#loading').html('' + $.t('admin.blacklist') + ' '); + + $.when(this.collection.fetch()).done(function() { + $('#loadingbox').sheet('hide'); + _self.render(); + }); + }, + + togglePlaceholder: function() { if (this.collection.length > 0) { $('#blacklist-table', this.el).show(); $('#blacklist-table-empty', this.el).hide(); @@ -81,136 +82,143 @@ var BlackListListView = Backbone.View.extend({ $('#blacklist-table-empty', this.el).show(); } }, - - render:function (eventName) { - + + render: function(eventName) { + $(this.el).html($('#tmpl-blacklist-table').html()); - + var _self = this; _.each(this.collection.models, function(blacklist) { - var view = new BlackListWidgetView({model: blacklist}); + var view = new BlackListWidgetView({ + model: blacklist + }); view.parentView = _self; $("#blacklist-table", _self.el).append(view.render().el); }, this); - + this.togglePlaceholder(); - - $(this.el).i18n(); + + $(this.el).i18n(); return this; }, - - addItem:function(e) { - e.preventDefault(); - - var input_value = $("#blacklist-uri", this.el).val().trim(); - - if (input_value === "") { - return; - } - - // TODO: URI/pattern validation, check against existing clients - - var item = new BlackListModel({ - uri: input_value - }); - - var _self = this; // closures... - - item.save({}, { - success:function() { - _self.collection.add(item); - _self.render(); - }, - error:app.errorHandlerView.handleError() - }); + + addItem: function(e) { + e.preventDefault(); + + var input_value = $("#blacklist-uri", this.el).val().trim(); + + if (input_value === "") { + return; + } + + // TODO: URI/pattern validation, check against existing clients + + var item = new BlackListModel({ + uri: input_value + }); + + var _self = this; // closures... + + item.save({}, { + success: function() { + _self.collection.add(item); + _self.render(); + }, + error: app.errorHandlerView.handleError() + }); } }); var BlackListWidgetView = Backbone.View.extend({ - + tagName: 'tr', - - initialize:function(options) { + + initialize: function(options) { this.options = options; - + if (!this.template) { this.template = _.template($('#tmpl-blacklist-item').html()); } }, - - render:function() { + + render: function() { this.$el.html(this.template(this.model.toJSON())); - return this; - + return this; + }, - - events:{ - 'click .btn-delete':'deleteBlacklist' + + events: { + 'click .btn-delete': 'deleteBlacklist' }, - - deleteBlacklist:function (e) { - e.preventDefault(); - - if (confirm($.t("blacklist.confirm"))) { - var _self = this; - - this.model.destroy({ - dataType: false, processData: false, - success:function () { - - _self.$el.fadeTo("fast", 0.00, function () { //fade - $(this).slideUp("fast", function () { //slide up - $(this).remove(); //then remove from the DOM - _self.parentView.togglePlaceholder(); - }); - }); - }, - error:app.errorHandlerView.handleError() - }); - - _self.parentView.delegateEvents(); - } - - return false; - } + + deleteBlacklist: function(e) { + e.preventDefault(); + + if (confirm($.t("blacklist.confirm"))) { + var _self = this; + + this.model.destroy({ + dataType: false, + processData: false, + success: function() { + + _self.$el.fadeTo("fast", 0.00, function() { // fade + $(this).slideUp("fast", function() { // slide up + $(this).remove(); // then remove from the DOM + _self.parentView.togglePlaceholder(); + }); + }); + }, + error: app.errorHandlerView.handleError() + }); + + _self.parentView.delegateEvents(); + } + + return false; + } }); +ui.routes.push({ + path: "admin/blacklist", + name: "blackList", + callback: function() { -ui.routes.push({path: "admin/blacklist", name: "blackList", callback: - function() { - if (!isAdmin()) { this.root(); return; } - + this.breadCrumbView.collection.reset(); - this.breadCrumbView.collection.add([ - {text:$.t('admin.home'), href:""}, - {text:$.t('admin.manage-blacklist'), href:"manage/#admin/blacklist"} - ]); - - this.updateSidebar('admin/blacklist'); - - var view = new BlackListListView({collection: this.blackListList}); - - view.load( - function(collection, response, options) { - $('#content').html(view.render().el); - setPageTitle($.t('admin.manage-blacklist')); - } - ); + this.breadCrumbView.collection.add([{ + text: $.t('admin.home'), + href: "" + }, { + text: $.t('admin.manage-blacklist'), + href: "manage/#admin/blacklist" + }]); + + this.updateSidebar('admin/blacklist'); + + var view = new BlackListListView({ + collection: this.blackListList + }); + + view.load(function(collection, response, options) { + $('#content').html(view.render().el); + setPageTitle($.t('admin.manage-blacklist')); + }); } -}); +}); ui.templates.push('resources/template/blacklist.html'); ui.init.push(function(app) { - app.blackListList = new BlackListCollection(); + app.blackListList = new BlackListCollection(); }); diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/client.js b/openid-connect-server-webapp/src/main/webapp/resources/js/client.js index fceea87493..e5e42a3107 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/client.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/client.js @@ -16,123 +16,123 @@ *******************************************************************************/ var ClientModel = Backbone.Model.extend({ - idAttribute: "id", - - initialize: function () { - - // bind validation errors to dom elements - // this will display form elements in red if they are not valid - this.bind('error', function(model, errs) { - _.map(errs, function (val, elID) { - $('#' + elID).addClass('error'); - }); - }); - - }, - - // We can pass it default values. - defaults:{ - id:null, - - clientId:null, - clientSecret:null, - redirectUris:[], - clientName:null, - clientUri:null, - logoUri:null, - contacts:[], - tosUri:null, - tokenEndpointAuthMethod:null, - scope:[], - grantTypes:[], - responseTypes:[], - policyUri:null, - - jwksUri:null, - jwks:null, - jwksType:"URI", - - applicationType:null, - sectorIdentifierUri:null, - subjectType:null, - - requestObjectSigningAlg:null, - - userInfoSignedResponseAlg:null, - userInfoEncryptedResponseAlg:null, - userInfoEncryptedResponseEnc:null, - - idTokenSignedResponseAlg:null, - idTokenEncryptedResponseAlg:null, - idTokenEncryptedResponseEnc:null, - - tokenEndpointAuthSigningAlg:null, - - defaultMaxAge:null, - requireAuthTime:false, - defaultACRvalues:null, - - initiateLoginUri:null, - postLogoutRedirectUris:[], - - requestUris:[], - - softwareStatement:null, - softwareId:null, - softwareVersion:null, - - codeChallengeMethod:null, - - authorities:[], - accessTokenValiditySeconds: null, - refreshTokenValiditySeconds: null, - resourceIds:[], - //additionalInformation? - - claimsRedirectUris:[], - - clientDescription:null, - reuseRefreshToken:true, - clearAccessTokensOnRefresh:true, - dynamicallyRegistered:false, - allowIntrospection:false, - idTokenValiditySeconds: null, - deviceCodeValiditySeconds: null, - createdAt:null, - - allowRefresh:false, - displayClientSecret: false, - generateClientSecret: false, - }, - - urlRoot:"api/clients", - - matches:function(term) { - - var matches = []; - - if (term) { - if (this.get('clientId').toLowerCase().indexOf(term.toLowerCase()) != -1) { - matches.push($.t('client.client-table.match.id')); - } - if (this.get('clientName') != null && this.get('clientName').toLowerCase().indexOf(term.toLowerCase()) != -1) { - matches.push($.t('client.client-table.match.name')); - } - if (this.get('clientDescription') != null && this.get('clientDescription').toLowerCase().indexOf(term.toLowerCase()) != -1) { - matches.push($.t('client.client-table.match.description')); - } - if (this.get('clientUri') != null && this.get('clientUri').toLowerCase().indexOf(term.toLowerCase()) != -1) { - matches.push($.t('client.client-table.match.homepage')); - } - if (this.get('policyUri') != null && this.get('policyUri').toLowerCase().indexOf(term.toLowerCase()) != -1) { - matches.push($.t('client.client-table.match.policy')); - } - if (this.get('tosUri') != null && this.get('tosUri').toLowerCase().indexOf(term.toLowerCase()) != -1) { - matches.push($.t('client.client-table.match.terms')); - } - if (this.get('logoUri') != null && this.get('logoUri').toLowerCase().indexOf(term.toLowerCase()) != -1) { - matches.push($.t('client.client-table.match.logo')); - } + idAttribute: "id", + + initialize: function() { + + // bind validation errors to dom elements + // this will display form elements in red if they are not valid + this.bind('error', function(model, errs) { + _.map(errs, function(val, elID) { + $('#' + elID).addClass('error'); + }); + }); + + }, + + // We can pass it default values. + defaults: { + id: null, + + clientId: null, + clientSecret: null, + redirectUris: [], + clientName: null, + clientUri: null, + logoUri: null, + contacts: [], + tosUri: null, + tokenEndpointAuthMethod: null, + scope: [], + grantTypes: [], + responseTypes: [], + policyUri: null, + + jwksUri: null, + jwks: null, + jwksType: "URI", + + applicationType: null, + sectorIdentifierUri: null, + subjectType: null, + + requestObjectSigningAlg: null, + + userInfoSignedResponseAlg: null, + userInfoEncryptedResponseAlg: null, + userInfoEncryptedResponseEnc: null, + + idTokenSignedResponseAlg: null, + idTokenEncryptedResponseAlg: null, + idTokenEncryptedResponseEnc: null, + + tokenEndpointAuthSigningAlg: null, + + defaultMaxAge: null, + requireAuthTime: false, + defaultACRvalues: null, + + initiateLoginUri: null, + postLogoutRedirectUris: [], + + requestUris: [], + + softwareStatement: null, + softwareId: null, + softwareVersion: null, + + codeChallengeMethod: null, + + authorities: [], + accessTokenValiditySeconds: null, + refreshTokenValiditySeconds: null, + resourceIds: [], + // additionalInformation? + + claimsRedirectUris: [], + + clientDescription: null, + reuseRefreshToken: true, + clearAccessTokensOnRefresh: true, + dynamicallyRegistered: false, + allowIntrospection: false, + idTokenValiditySeconds: null, + deviceCodeValiditySeconds: null, + createdAt: null, + + allowRefresh: false, + displayClientSecret: false, + generateClientSecret: false, + }, + + urlRoot: "api/clients", + + matches: function(term) { + + var matches = []; + + if (term) { + if (this.get('clientId').toLowerCase().indexOf(term.toLowerCase()) != -1) { + matches.push($.t('client.client-table.match.id')); + } + if (this.get('clientName') != null && this.get('clientName').toLowerCase().indexOf(term.toLowerCase()) != -1) { + matches.push($.t('client.client-table.match.name')); + } + if (this.get('clientDescription') != null && this.get('clientDescription').toLowerCase().indexOf(term.toLowerCase()) != -1) { + matches.push($.t('client.client-table.match.description')); + } + if (this.get('clientUri') != null && this.get('clientUri').toLowerCase().indexOf(term.toLowerCase()) != -1) { + matches.push($.t('client.client-table.match.homepage')); + } + if (this.get('policyUri') != null && this.get('policyUri').toLowerCase().indexOf(term.toLowerCase()) != -1) { + matches.push($.t('client.client-table.match.policy')); + } + if (this.get('tosUri') != null && this.get('tosUri').toLowerCase().indexOf(term.toLowerCase()) != -1) { + matches.push($.t('client.client-table.match.terms')); + } + if (this.get('logoUri') != null && this.get('logoUri').toLowerCase().indexOf(term.toLowerCase()) != -1) { + matches.push($.t('client.client-table.match.logo')); + } if (this.get('contacts') != null) { var f = _.filter(this.get('contacts'), function(item) { return item.toLowerCase().indexOf(term.toLowerCase()) != -1; @@ -142,7 +142,7 @@ var ClientModel = Backbone.Model.extend({ } } if (this.get('redirectUris') != null) { - var f = _.filter(this.get('redirectUris'), function (item) { + var f = _.filter(this.get('redirectUris'), function(item) { return item.toLowerCase().indexOf(term.toLowerCase()) != -1; }); if (f.length > 0) { @@ -150,7 +150,7 @@ var ClientModel = Backbone.Model.extend({ } } if (this.get('scope') != null) { - var f = _.filter(this.get('scope'), function (item) { + var f = _.filter(this.get('scope'), function(item) { return item.toLowerCase().indexOf(term.toLowerCase()) != -1; }); if (f.length > 0) { @@ -163,29 +163,34 @@ var ClientModel = Backbone.Model.extend({ if (this.get('softwareVersion') != null && this.get('softwareVersion').toLowerCase().indexOf(term.toLowerCase()) != -1) { matches.push($.t('client.client-table.match.software-version')); } - } else { - // there's no search term, we always match - - this.unset('matches', {silent: true}); - //console.log('no term'); - return true; - } - - - var matchString = matches.join(' | '); - - if (matches.length > 0) { - this.set({ - matches: matchString - }, {silent: true}); - - return true; - } else { - this.unset('matches', {silent: true}); - - return false; - } - } + } else { + // there's no search term, we always match + + this.unset('matches', { + silent: true + }); + // console.log('no term'); + return true; + } + + var matchString = matches.join(' | '); + + if (matches.length > 0) { + this.set({ + matches: matchString + }, { + silent: true + }); + + return true; + } else { + this.unset('matches', { + silent: true + }); + + return false; + } + } }); @@ -195,64 +200,66 @@ var RegistrationTokenModel = Backbone.Model.extend({ }); var ClientStatsModel = Backbone.Model.extend({ - urlRoot: 'api/stats/byclientid' + urlRoot: 'api/stats/byclientid' }); var ClientCollection = Backbone.Collection.extend({ - initialize: function() { - //this.fetch(); - }, + initialize: function() { + // this.fetch(); + }, + + model: ClientModel, + url: "api/clients", - model:ClientModel, - url:"api/clients", - - getByClientId: function(clientId) { - var clients = this.where({clientId: clientId}); + getByClientId: function(clientId) { + var clients = this.where({ + clientId: clientId + }); if (clients.length == 1) { return clients[0]; } else { return null; } - } + } }); var ClientView = Backbone.View.extend({ - tagName: 'tr', - - isRendered: false, - - initialize:function (options) { - this.options = options; - - if (!this.template) { - this.template = _.template($('#tmpl-client-table-item').html()); - } - - if (!this.scopeTemplate) { - this.scopeTemplate = _.template($('#tmpl-scope-list').html()); - } - - if (!this.moreInfoTemplate) { - this.moreInfoTemplate = _.template($('#tmpl-client-more-info-block').html()); - } - - if (!this.registrationTokenTemplate) { - this.registrationTokenTemplate = _.template($('#tmpl-client-registration-token').html()); - } - - if (!this.countTemplate) { - this.countTemplate = _.template($('#tmpl-client-count').html()); - } - - this.model.bind('change', this.render, this); - - }, - - render:function (eventName) { - - var creationDate = this.model.get('createdAt'); + tagName: 'tr', + + isRendered: false, + + initialize: function(options) { + this.options = options; + + if (!this.template) { + this.template = _.template($('#tmpl-client-table-item').html()); + } + + if (!this.scopeTemplate) { + this.scopeTemplate = _.template($('#tmpl-scope-list').html()); + } + + if (!this.moreInfoTemplate) { + this.moreInfoTemplate = _.template($('#tmpl-client-more-info-block').html()); + } + + if (!this.registrationTokenTemplate) { + this.registrationTokenTemplate = _.template($('#tmpl-client-registration-token').html()); + } + + if (!this.countTemplate) { + this.countTemplate = _.template($('#tmpl-client-count').html()); + } + + this.model.bind('change', this.render, this); + + }, + + render: function(eventName) { + + var creationDate = this.model.get('createdAt'); var displayCreationDate = $.t('client.client-table.unknown'); var hoverCreationDate = ""; if (creationDate == null || !moment(creationDate).isValid()) { @@ -268,144 +275,176 @@ var ClientView = Backbone.View.extend({ hoverCreationDate = creationDate.format("LLL"); } - - var json = {client: this.model.toJSON(), whiteList: this.options.whiteList, - displayCreationDate: displayCreationDate, hoverCreationDate: hoverCreationDate}; - this.$el.html(this.template(json)); - - $('.scope-list', this.el).html(this.scopeTemplate({scopes: this.model.get('scope'), systemScopes: this.options.systemScopeList})); - - $('.client-more-info-block', this.el).html(this.moreInfoTemplate({client: this.model.toJSON()})); - - $('.clientid-full', this.el).hide(); - - this.$('.dynamically-registered').tooltip({title: $.t('client.client-table.dynamically-registered-tooltip')}); - this.$('.allow-introspection').tooltip({title: $.t('client.client-table.allow-introspection-tooltip')}); - - this.updateMatched(); - this.updateStats(); - - $(this.el).i18n(); - - this.isRendered = true; - - return this; - }, - - updateStats:function(eventName) { - $('.count', this.el).html(this.countTemplate({count: this.options.clientStat.get('approvedSiteCount')})); - }, - - showRegistrationToken:function(e) { - e.preventDefault(); - - $('#modalAlertLabel').html($.t('client.client-form.registration-access-token')); - - var token = new RegistrationTokenModel({clientId: this.model.get('clientId')}); - - var _self = this; - token.fetch({success:function() { - var savedModel = { - clientId: _self.model.get('clientId'), - registrationToken: token.get('value') - }; - - $('#modalAlert .modal-body').html(_self.registrationTokenTemplate(savedModel)); - - $('#modalAlert .modal-body #rotate-token').click(function(e) { - if (confirm($.t('client.client-form.rotate-registration-token-confirm'))) { - token.save(null, {success: function() { - console.log('token:' + token.get('value')); - $('#modalAlert .modal-body #registrationToken').val(token.get('value')); - }, - error: app.errorHandlerView.handleError({message: $.t('client.client-form.rotate-registration-token-error')}) - }); - } - }); - - $('#modalAlert').i18n(); - $('#modalAlert').modal({ - 'backdrop': 'static', - 'keyboard': true, - 'show': true - }); - - }, - error:app.errorHandlerView.handleError({log: "An error occurred when fetching the registration token", message: $.t('client.client-form.registration-token-error')}) - }); - - }, - - updateMatched:function() { - - //console.log(this.model.get('matches')); - - if (this.model.get('matches')) { - $('.matched', this.el).show(); - $('.matched span', this.el).html(this.model.get('matches')); - } else { - $('.matched', this.el).hide(); - } - }, - - events:{ - "click .btn-edit":"editClient", - "click .btn-delete":"deleteClient", - "click .btn-whitelist":"whiteListClient", + var json = { + client: this.model.toJSON(), + whiteList: this.options.whiteList, + displayCreationDate: displayCreationDate, + hoverCreationDate: hoverCreationDate + }; + this.$el.html(this.template(json)); + + $('.scope-list', this.el).html(this.scopeTemplate({ + scopes: this.model.get('scope'), + systemScopes: this.options.systemScopeList + })); + + $('.client-more-info-block', this.el).html(this.moreInfoTemplate({ + client: this.model.toJSON() + })); + + $('.clientid-full', this.el).hide(); + + this.$('.dynamically-registered').tooltip({ + title: $.t('client.client-table.dynamically-registered-tooltip') + }); + this.$('.allow-introspection').tooltip({ + title: $.t('client.client-table.allow-introspection-tooltip') + }); + + this.updateMatched(); + this.updateStats(); + + $(this.el).i18n(); + + this.isRendered = true; + + return this; + }, + + updateStats: function(eventName) { + $('.count', this.el).html(this.countTemplate({ + count: this.options.clientStat.get('approvedSiteCount') + })); + }, + + showRegistrationToken: function(e) { + e.preventDefault(); + + $('#modalAlertLabel').html($.t('client.client-form.registration-access-token')); + + var token = new RegistrationTokenModel({ + clientId: this.model.get('clientId') + }); + + var _self = this; + token.fetch({ + success: function() { + var savedModel = { + clientId: _self.model.get('clientId'), + registrationToken: token.get('value') + }; + + $('#modalAlert .modal-body').html(_self.registrationTokenTemplate(savedModel)); + + $('#modalAlert .modal-body #rotate-token').click(function(e) { + if (confirm($.t('client.client-form.rotate-registration-token-confirm'))) { + token.save(null, { + success: function() { + console.log('token:' + token.get('value')); + $('#modalAlert .modal-body #registrationToken').val(token.get('value')); + }, + error: app.errorHandlerView.handleError({ + message: $.t('client.client-form.rotate-registration-token-error') + }) + }); + } + }); + + $('#modalAlert').i18n(); + $('#modalAlert').modal({ + 'backdrop': 'static', + 'keyboard': true, + 'show': true + }); + + }, + error: app.errorHandlerView.handleError({ + log: "An error occurred when fetching the registration token", + message: $.t('client.client-form.registration-token-error') + }) + }); + + }, + + updateMatched: function() { + + // console.log(this.model.get('matches')); + + if (this.model.get('matches')) { + $('.matched', this.el).show(); + $('.matched span', this.el).html(this.model.get('matches')); + } else { + $('.matched', this.el).hide(); + } + }, + + events: { + "click .btn-edit": "editClient", + "click .btn-delete": "deleteClient", + "click .btn-whitelist": "whiteListClient", 'click .toggleMoreInformation': 'toggleMoreInformation', - "click .clientid-substring":"showClientId", - "click .dynamically-registered": 'showRegistrationToken' - }, - - editClient:function (e) { - e.preventDefault(); - app.navigate('admin/client/' + this.model.id, {trigger: true}); - }, - - whiteListClient:function(e) { - e.preventDefault(); - if (this.options.whiteList == null) { - // create a new one - app.navigate('admin/whitelist/new/' + this.model.get('id'), {trigger: true}); - } else { - // edit the existing one - app.navigate('admin/whitelist/' + this.options.whiteList.get('id'), {trigger: true}); - } - }, - - deleteClient:function (e) { - e.preventDefault(); - - if (confirm($.t('client.client-table.confirm'))) { - var _self = this; - - this.model.destroy({ - dataType: false, processData: false, - success:function () { - _self.$el.fadeTo("fast", 0.00, function () { //fade - $(this).slideUp("fast", function () { //slide up - $(this).remove(); //then remove from the DOM - _self.parentView.togglePlaceholder(); - }); - }); - }, - error:app.errorHandlerView.handleError({log: "An error occurred when deleting a client"}) - }); - - _self.parentView.delegateEvents(); - } - - return false; - }, - - toggleMoreInformation:function(e) { + "click .clientid-substring": "showClientId", + "click .dynamically-registered": 'showRegistrationToken' + }, + + editClient: function(e) { + e.preventDefault(); + app.navigate('admin/client/' + this.model.id, { + trigger: true + }); + }, + + whiteListClient: function(e) { + e.preventDefault(); + if (this.options.whiteList == null) { + // create a new one + app.navigate('admin/whitelist/new/' + this.model.get('id'), { + trigger: true + }); + } else { + // edit the existing one + app.navigate('admin/whitelist/' + this.options.whiteList.get('id'), { + trigger: true + }); + } + }, + + deleteClient: function(e) { + e.preventDefault(); + + if (confirm($.t('client.client-table.confirm'))) { + var _self = this; + + this.model.destroy({ + dataType: false, + processData: false, + success: function() { + _self.$el.fadeTo("fast", 0.00, function() { // fade + $(this).slideUp("fast", function() { // slide up + $(this).remove(); // then remove from the DOM + _self.parentView.togglePlaceholder(); + }); + }); + }, + error: app.errorHandlerView.handleError({ + log: "An error occurred when deleting a client" + }) + }); + + _self.parentView.delegateEvents(); + } + + return false; + }, + + toggleMoreInformation: function(e) { e.preventDefault(); if ($('.moreInformation', this.el).is(':visible')) { // hide it $('.moreInformationContainer', this.el).removeClass('alert').removeClass('alert-info').addClass('muted'); $('.moreInformation', this.el).hide('fast'); $('.toggleMoreInformation i', this.el).attr('class', 'icon-chevron-right'); - + } else { // show it $('.moreInformationContainer', this.el).addClass('alert').addClass('alert-info').removeClass('muted'); @@ -413,134 +452,145 @@ var ClientView = Backbone.View.extend({ $('.toggleMoreInformation i', this.el).attr('class', 'icon-chevron-down'); } }, - - showClientId:function(e) { + + showClientId: function(e) { e.preventDefault(); - + $('.clientid-full', this.el).show(); - + }, - - close:function () { - $(this.el).unbind(); - $(this.el).empty(); - } + + close: function() { + $(this.el).unbind(); + $(this.el).empty(); + } }); var ClientListView = Backbone.View.extend({ - tagName: 'span', - - stats: {}, - - initialize:function (options) { - this.options = options; - this.filteredModel = this.model; - }, - - load:function(callback) { - if (this.model.isFetched && - this.options.whiteListList.isFetched && - this.options.systemScopeList.isFetched) { - callback(); - return; - } - - $('#loadingbox').sheet('show'); - $('#loading').html( - '' + $.t("common.clients") + ' ' + - '' + $.t("whitelist.whitelist") + ' ' + - '' + $.t("common.scopes") + ' ' - ); - - $.when(this.model.fetchIfNeeded({success:function(e) {$('#loading-clients').addClass('label-success');}, error:app.errorHandlerView.handleError()}), - this.options.whiteListList.fetchIfNeeded({success:function(e) {$('#loading-whitelist').addClass('label-success');}, error:app.errorHandlerView.handleError()}), - this.options.systemScopeList.fetchIfNeeded({success:function(e) {$('#loading-scopes').addClass('label-success');}, error:app.errorHandlerView.handleError()})) - .done(function() { - $('#loadingbox').sheet('hide'); - callback(); - }); - - }, - - events:{ - "click .new-client":"newClient", - "click .refresh-table":"refreshTable", - 'keyup .search-query':'searchTable', - 'click .form-search button':'clearSearch', - 'page .paginator':'changePage' - }, - - newClient:function (e) { - e.preventDefault(); - this.remove(); - app.navigate('admin/client/new', {trigger: true}); - }, - - render:function (eventName) { - - // append and render table structure - $(this.el).html($('#tmpl-client-table').html()); - - this.renderInner(); - $(this.el).i18n(); - return this; - }, - - renderInner:function(eventName) { - - // set up the rows to render - // (note that this doesn't render until visibility is determined in togglePlaceholder) - - _.each(this.filteredModel.models, function (client, index) { - var clientStat = this.getStat(client.get('clientId')); - var view = new ClientView({ - model:client, - clientStat:clientStat, + tagName: 'span', + + stats: {}, + + initialize: function(options) { + this.options = options; + this.filteredModel = this.model; + }, + + load: function(callback) { + if (this.model.isFetched && this.options.whiteListList.isFetched && this.options.systemScopeList.isFetched) { + callback(); + return; + } + + $('#loadingbox').sheet('show'); + $('#loading').html('' + $.t("common.clients") + ' ' + '' + $.t("whitelist.whitelist") + ' ' + '' + $.t("common.scopes") + ' '); + + $.when(this.model.fetchIfNeeded({ + success: function(e) { + $('#loading-clients').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + }), this.options.whiteListList.fetchIfNeeded({ + success: function(e) { + $('#loading-whitelist').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + }), this.options.systemScopeList.fetchIfNeeded({ + success: function(e) { + $('#loading-scopes').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + })).done(function() { + $('#loadingbox').sheet('hide'); + callback(); + }); + + }, + + events: { + "click .new-client": "newClient", + "click .refresh-table": "refreshTable", + 'keyup .search-query': 'searchTable', + 'click .form-search button': 'clearSearch', + 'page .paginator': 'changePage' + }, + + newClient: function(e) { + e.preventDefault(); + this.remove(); + app.navigate('admin/client/new', { + trigger: true + }); + }, + + render: function(eventName) { + + // append and render table structure + $(this.el).html($('#tmpl-client-table').html()); + + this.renderInner(); + $(this.el).i18n(); + return this; + }, + + renderInner: function(eventName) { + + // set up the rows to render + // (note that this doesn't render until visibility is determined in + // togglePlaceholder) + + _.each(this.filteredModel.models, function(client, index) { + var clientStat = this.getStat(client.get('clientId')); + var view = new ClientView({ + model: client, + clientStat: clientStat, systemScopeList: this.options.systemScopeList, whiteList: this.options.whiteListList.getByClientId(client.get('clientId')) }); - view.parentView = this; - //var element = view.render().el; - var element = view.el; - $("#client-table",this.el).append(element); - this.addView(client.get('id'), view); - }, this); - - this.togglePlaceholder(); - }, - - views:{}, - - addView:function(index, view) { - this.views[index] = view; - }, - - getView:function(index) { - return this.views[index]; - }, - - getStat:function(index) { + view.parentView = this; + // var element = view.render().el; + var element = view.el; + $("#client-table", this.el).append(element); + this.addView(client.get('id'), view); + }, this); + + this.togglePlaceholder(); + }, + + views: {}, + + addView: function(index, view) { + this.views[index] = view; + }, + + getView: function(index) { + return this.views[index]; + }, + + getStat: function(index) { if (!this.stats[index]) { - this.stats[index] = new ClientStatsModel({id: index}); + this.stats[index] = new ClientStatsModel({ + id: index + }); } return this.stats[index]; }, - - togglePlaceholder:function() { - // set up pagination - var numPages = Math.ceil(this.filteredModel.length / 10); - if (numPages > 1) { - $('.paginator', this.el).show(); - $('.paginator', this.el).bootpag({ - total: numPages, - maxVisible: 10, - leaps: false, - page: 1 - }); - } else { - $('.paginator', this.el).hide(); - } + + togglePlaceholder: function() { + // set up pagination + var numPages = Math.ceil(this.filteredModel.length / 10); + if (numPages > 1) { + $('.paginator', this.el).show(); + $('.paginator', this.el).bootpag({ + total: numPages, + maxVisible: 10, + leaps: false, + page: 1 + }); + } else { + $('.paginator', this.el).hide(); + } if (this.filteredModel.length > 0) { this.changePage(undefined, 1); @@ -561,867 +611,947 @@ var ClientListView = Backbone.View.extend({ } } }, - - changePage:function(event, num) { + + changePage: function(event, num) { console.log('Page changed: ' + num); - - $('.paginator', this.el).bootpag({page:num}); + + $('.paginator', this.el).bootpag({ + page: num + }); var _self = this; - - _.each(this.filteredModel.models, function (client, index) { - var view = _self.getView(client.get('id')); - if (!view) { - console.log('Error: no view for client ' + client.get('id')); - return; - } - - // only show/render clients on the current page - - console.log(':: ' + index + ' ' + num + ' ' + Math.ceil((index + 1) / 10) != num); - - if (Math.ceil((index + 1) / 10) != num) { - $(view.el).hide(); - } else { - if (!view.isRendered) { - view.render(); - var clientStat = view.options.clientStat; - - // load and display the stats - $.when(clientStat.fetchIfNeeded({ - success:function(e) { - - }, - error:app.errorHandlerView.handleError()})) - .done(function(e) { - view.updateStats(); - }); - } - $(view.el).show(); - } - }); - - /* - $('#client-table tbody tr', this.el).each(function(index, element) { + + _.each(this.filteredModel.models, function(client, index) { + var view = _self.getView(client.get('id')); + if (!view) { + console.log('Error: no view for client ' + client.get('id')); + return; + } + + // only show/render clients on the current page + + console.log(':: ' + index + ' ' + num + ' ' + Math.ceil((index + 1) / 10) != num); + if (Math.ceil((index + 1) / 10) != num) { - // hide the element - $(element).hide(); - } else { - // show the element - $(element).show(); - } + $(view.el).hide(); + } else { + if (!view.isRendered) { + view.render(); + var clientStat = view.options.clientStat; + + // load and display the stats + $.when(clientStat.fetchIfNeeded({ + success: function(e) { + + }, + error: app.errorHandlerView.handleError() + })).done(function(e) { + view.updateStats(); + }); + } + $(view.el).show(); + } + }); + + /* + * $('#client-table tbody tr', this.el).each(function(index, element) { + * if (Math.ceil((index + 1) / 10) != num) { // hide the element + * $(element).hide(); } else { // show the element $(element).show(); } + * }); + */ + }, + + refreshTable: function(e) { + e.preventDefault(); + $('#loadingbox').sheet('show'); + $('#loading').html('' + $.t("common.clients") + ' ' + '' + $.t("whitelist.whitelist") + ' ' + '' + $.t("common.scopes") + ' '); + + var _self = this; + $.when(this.model.fetch({ + success: function(e) { + $('#loading-clients').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + }), this.options.whiteListList.fetch({ + success: function(e) { + $('#loading-whitelist').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + }), this.options.systemScopeList.fetch({ + success: function(e) { + $('#loading-scopes').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + })).done(function() { + $('#loadingbox').sheet('hide'); + _self.render(); }); - */ }, - - refreshTable:function(e) { - e.preventDefault(); - $('#loadingbox').sheet('show'); - $('#loading').html( - '' + $.t("common.clients") + ' ' + - '' + $.t("whitelist.whitelist") + ' ' + - '' + $.t("common.scopes") + ' ' - ); - - var _self = this; - $.when(this.model.fetch({success:function(e) {$('#loading-clients').addClass('label-success');}, error:app.errorHandlerView.handleError()}), - this.options.whiteListList.fetch({success:function(e) {$('#loading-whitelist').addClass('label-success');}, error:app.errorHandlerView.handleError()}), - this.options.systemScopeList.fetch({success:function(e) {$('#loading-scopes').addClass('label-success');}, error:app.errorHandlerView.handleError()})) - .done(function() { - $('#loadingbox').sheet('hide'); - _self.render(); - }); - }, - - searchTable:function(e) { - var term = $('.search-query', this.el).val(); - + + searchTable: function(e) { + var term = $('.search-query', this.el).val(); + this.filteredModel = new ClientCollection(this.model.filter(function(client) { return client.matches(term); })); - - // clear out the table - $('tbody', this.el).html(''); - - // re-render the table - this.renderInner(); - - }, - - clearSearch:function(e) { - $('.search-query', this.el).val(''); - this.searchTable(); - } - - + + // clear out the table + $('tbody', this.el).html(''); + + // re-render the table + this.renderInner(); + + }, + + clearSearch: function(e) { + $('.search-query', this.el).val(''); + this.searchTable(); + } + }); var ClientFormView = Backbone.View.extend({ - tagName:"span", - - initialize:function (options) { - this.options = options; - - if (!this.template) { - this.template = _.template($('#tmpl-client-form').html()); - } - - if (!this.clientSavedTemplate) { - this.clientSavedTemplate = _.template($('#tmpl-client-saved').html()); - } - - this.redirectUrisCollection = new Backbone.Collection(); - this.scopeCollection = new Backbone.Collection(); - this.contactsCollection = new Backbone.Collection(); - this.defaultACRvaluesCollection = new Backbone.Collection(); - this.requestUrisCollection = new Backbone.Collection(); - this.postLogoutRedirectUrisCollection = new Backbone.Collection(); - this.claimsRedirectUrisCollection = new Backbone.Collection(); - // TODO: add Spring authorities collection and resource IDs collection? - - // collection of sub-views that need to be sync'd on save - this.listWidgetViews = []; - }, - - events:{ - "click .btn-save":"saveClient", - "click #allowRefresh" : "toggleRefreshTokenTimeout", - "click #disableAccessTokenTimeout" : function() { - $("#access-token-timeout-time", this.$el).prop('disabled',!$("#access-token-timeout-time", this.$el).prop('disabled')); - $("#access-token-timeout-unit", this.$el).prop('disabled',!$("#access-token-timeout-unit", this.$el).prop('disabled')); - document.getElementById("access-token-timeout-time").value = ''; - }, - "click #disableRefreshTokenTimeout" : function() { - $("#refresh-token-timeout-time", this.$el).prop('disabled',!$("#refresh-token-timeout-time", this.$el).prop('disabled')); - $("#refresh-token-timeout-unit", this.$el).prop('disabled',!$("#refresh-token-timeout-unit", this.$el).prop('disabled')); - document.getElementById("refresh-token-timeout-time").value = ''; - }, - "click .btn-cancel":"cancel", - "change #tokenEndpointAuthMethod input:radio":"toggleClientCredentials", - "change #displayClientSecret":"toggleDisplayClientSecret", - "change #generateClientSecret":"toggleGenerateClientSecret", - "change #logoUri input":"previewLogo", - "change #jwkSelector input:radio":"toggleJWKSetType" - }, - - cancel:function(e) { - e.preventDefault(); - app.navigate('admin/clients', {trigger: true}); - }, - - load:function(callback) { - if (this.model.isFetched && - this.options.systemScopeList.isFetched) { - callback(); - return; - } - - $('#loadingbox').sheet('show'); - $('#loading').html( - '' + $.t('common.clients') + ' ' + - '' + $.t("common.scopes") + ' ' - ); - - $.when(this.options.systemScopeList.fetchIfNeeded({success:function(e) {$('#loading-scopes').addClass('label-success');}, error:app.errorHandlerView.handleError()}), - this.model.fetchIfNeeded({success:function(e) {$('#loading-clients').addClass('label-success');}, error:app.errorHandlerView.handleError()})) - .done(function() { - $('#loadingbox').sheet('hide'); - callback(); - }); + tagName: "span", + + initialize: function(options) { + this.options = options; + + if (!this.template) { + this.template = _.template($('#tmpl-client-form').html()); + } + + if (!this.clientSavedTemplate) { + this.clientSavedTemplate = _.template($('#tmpl-client-saved').html()); + } + + this.redirectUrisCollection = new Backbone.Collection(); + this.scopeCollection = new Backbone.Collection(); + this.contactsCollection = new Backbone.Collection(); + this.defaultACRvaluesCollection = new Backbone.Collection(); + this.requestUrisCollection = new Backbone.Collection(); + this.postLogoutRedirectUrisCollection = new Backbone.Collection(); + this.claimsRedirectUrisCollection = new Backbone.Collection(); + // TODO: add Spring authorities collection and resource IDs collection? + + // collection of sub-views that need to be sync'd on save + this.listWidgetViews = []; + }, + + events: { + "click .btn-save": "saveClient", + "click #allowRefresh": "toggleRefreshTokenTimeout", + "click #disableAccessTokenTimeout": function() { + $("#access-token-timeout-time", this.$el).prop('disabled', !$("#access-token-timeout-time", this.$el).prop('disabled')); + $("#access-token-timeout-unit", this.$el).prop('disabled', !$("#access-token-timeout-unit", this.$el).prop('disabled')); + document.getElementById("access-token-timeout-time").value = ''; + }, + "click #disableRefreshTokenTimeout": function() { + $("#refresh-token-timeout-time", this.$el).prop('disabled', !$("#refresh-token-timeout-time", this.$el).prop('disabled')); + $("#refresh-token-timeout-unit", this.$el).prop('disabled', !$("#refresh-token-timeout-unit", this.$el).prop('disabled')); + document.getElementById("refresh-token-timeout-time").value = ''; + }, + "click .btn-cancel": "cancel", + "change #tokenEndpointAuthMethod input:radio": "toggleClientCredentials", + "change #displayClientSecret": "toggleDisplayClientSecret", + "change #generateClientSecret": "toggleGenerateClientSecret", + "change #logoUri input": "previewLogo", + "change #jwkSelector input:radio": "toggleJWKSetType" + }, + + cancel: function(e) { + e.preventDefault(); + app.navigate('admin/clients', { + trigger: true + }); + }, + + load: function(callback) { + if (this.model.isFetched && this.options.systemScopeList.isFetched) { + callback(); + return; + } + + $('#loadingbox').sheet('show'); + $('#loading').html('' + $.t('common.clients') + ' ' + '' + $.t("common.scopes") + ' '); + + $.when(this.options.systemScopeList.fetchIfNeeded({ + success: function(e) { + $('#loading-scopes').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + }), this.model.fetchIfNeeded({ + success: function(e) { + $('#loading-clients').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + })).done(function() { + $('#loadingbox').sheet('hide'); + callback(); + }); + }, + + toggleRefreshTokenTimeout: function() { + $("#refreshTokenValidityTime", this.$el).toggle(); }, - - toggleRefreshTokenTimeout:function () { - $("#refreshTokenValidityTime", this.$el).toggle(); - }, - - previewLogo:function() { - if ($('#logoUri input', this.el).val()) { - $('#logoPreview', this.el).empty(); - $('#logoPreview', this.el).attr('src', $('#logoUri input', this.el).val()); - } else { - //$('#logoBlock', this.el).hide(); - $('#logoPreview', this.el).attr('src', 'resources/images/logo_placeholder.gif'); - } - }, - - /** - * Set up the form based on the current state of the tokenEndpointAuthMethod parameter - * @param event - */ - toggleClientCredentials:function() { - - var tokenEndpointAuthMethod = $('#tokenEndpointAuthMethod input', this.el).filter(':checked').val(); - - if (tokenEndpointAuthMethod == 'SECRET_BASIC' - || tokenEndpointAuthMethod == 'SECRET_POST' - || tokenEndpointAuthMethod == 'SECRET_JWT') { - - // client secret is required, show all the bits - $('#clientSecretPanel', this.el).show(); - // this function sets up the display portions - this.toggleGenerateClientSecret(); - } else { - // no client secret, hide all the bits - $('#clientSecretPanel', this.el).hide(); - } - - // show or hide the signing algorithm method depending on what's selected - if (tokenEndpointAuthMethod == 'PRIVATE_KEY' - || tokenEndpointAuthMethod == 'SECRET_JWT') { - $('#tokenEndpointAuthSigningAlg', this.el).show(); - } else { - $('#tokenEndpointAuthSigningAlg', this.el).hide(); - } - }, - - /** - * Set up the form based on the JWK Set selector - */ - toggleJWKSetType:function() { - var jwkSelector = $('#jwkSelector input:radio', this.el).filter(':checked').val(); - - if (jwkSelector == 'URI') { - $('#jwksUri', this.el).show(); - $('#jwks', this.el).hide(); - } else if (jwkSelector == 'VAL') { - $('#jwksUri', this.el).hide(); - $('#jwks', this.el).show(); - } else { - $('#jwksUri', this.el).hide(); - $('#jwks', this.el).hide(); - } - - }, - - /** - * Set up the form based on the "Generate" checkbox - * @param event - */ - toggleGenerateClientSecret:function() { - - if ($('#generateClientSecret input', this.el).is(':checked')) { - // show the "generated" block, hide the "display" checkbox - $('#displayClientSecret', this.el).hide(); - $('#clientSecret', this.el).hide(); - $('#clientSecretGenerated', this.el).show(); - $('#clientSecretHidden', this.el).hide(); - } else { - // show the display checkbox, fall back to the "display" logic - $('#displayClientSecret', this.el).show(); - this.toggleDisplayClientSecret(); - } - }, - - /** - * Handle whether or not to display the client secret - * @param event - */ - toggleDisplayClientSecret:function() { - - if ($('#displayClientSecret input').is(':checked')) { - // want to display it - $('#clientSecret', this.el).show(); - $('#clientSecretHidden', this.el).hide(); - $('#clientSecretGenerated', this.el).hide(); - } else { - // want to hide it - $('#clientSecret', this.el).hide(); - $('#clientSecretHidden', this.el).show(); - $('#clientSecretGenerated', this.el).hide(); - } - }, - - // rounds down to the nearest integer value in seconds. - getFormTokenNumberValue:function(value, timeUnit) { - if (value == "") { - return null; - } else if (timeUnit == 'hours') { - return parseInt(parseFloat(value) * 3600); - } else if (timeUnit == 'minutes') { - return parseInt(parseFloat(value) * 60); - } else { // seconds - return parseInt(value); - } - }, - - // returns "null" if given the value "default" as a string, otherwise returns input value. useful for parsing the JOSE algorithm dropdowns - defaultToNull:function(value) { - if (value == 'default') { - return null; - } else { - return value; - } - }, - - // returns "null" if the given value is falsy - emptyToNull:function(value) { - if (value) { - return value; - } else { - return null; - } - }, - - disableUnsupportedJOSEItems:function(serverSupported, query) { - var supported = ['default']; - if (serverSupported) { - supported = _.union(supported, serverSupported); - } - $(query, this.$el).each(function(idx) { - if(_.contains(supported, $(this).val())) { - $(this).prop('disabled', false); - } else { - $(this).prop('disabled', true); - } - }); - - }, - - // maps from a form-friendly name to the real grant parameter name - grantMap:{ - 'authorization_code': 'authorization_code', - 'password': 'password', - 'implicit': 'implicit', - 'client_credentials': 'client_credentials', - 'redelegate': 'urn:ietf:params:oauth:grant_type:redelegate', - 'refresh_token': 'refresh_token', - 'device': 'urn:ietf:params:oauth:grant-type:device_code' - }, - - // maps from a form-friendly name to the real response type parameter name - responseMap:{ - 'code': 'code', - 'token': 'token', - 'idtoken': 'id_token', - 'token-idtoken': 'token id_token', - 'code-idtoken': 'code id_token', - 'code-token': 'code token', - 'code-token-idtoken': 'code token id_token' - }, - - saveClient:function (event) { - - $('.control-group').removeClass('error'); - - // sync any leftover collection items - _.each(this.listWidgetViews, function(v) { - v.addItem($.Event('click')); - }); - - // build the scope object - var scopes = this.scopeCollection.pluck("item"); - - // build the grant type object - var grantTypes = []; - $.each(this.grantMap, function(index,type) { - if ($('#grantTypes-' + index).is(':checked')) { - grantTypes.push(type); - } - }); - - // build the response type object - var responseTypes = []; - $.each(this.responseMap, function(index,type) { - if ($('#responseTypes-' + index).is(':checked')) { - responseTypes.push(type); - } - }); - - var generateClientSecret = $('#generateClientSecret input').is(':checked'); - var clientSecret = null; - - var tokenEndpointAuthMethod = $('#tokenEndpointAuthMethod input').filter(':checked').val(); - - // whether or not the client secret changed - var secretChanged = false; - - if (tokenEndpointAuthMethod == 'SECRET_BASIC' - || tokenEndpointAuthMethod == 'SECRET_POST' - || tokenEndpointAuthMethod == 'SECRET_JWT') { - - if (!generateClientSecret) { - // if it's required but we're not generating it, send the value to preserve it - clientSecret = $('#clientSecret input').val(); - - // if it's not the same as before, offer to display it - if (clientSecret != this.model.get('clientSecret')) { - secretChanged = true; - } - } else { - // it's being generated anew - secretChanged = true; - } - } - - var accessTokenValiditySeconds = null; - if (!$('disableAccessTokenTimeout').is(':checked')) { - accessTokenValiditySeconds = this.getFormTokenNumberValue($('#accessTokenValidityTime input[type=text]').val(), $('#accessTokenValidityTime select').val()); - } - - var idTokenValiditySeconds = this.getFormTokenNumberValue($('#idTokenValidityTime input[type=text]').val(), $('#idTokenValidityTime select').val()); - - var deviceCodeValiditySeconds = this.getFormTokenNumberValue($('#deviceCodeValidityTime input[type=text]').val(), $('#deviceCodeValidityTime select').val()); - - var refreshTokenValiditySeconds = null; - if ($('#allowRefresh').is(':checked')) { - - if ($.inArray('refresh_token', grantTypes) == -1) { - grantTypes.push('refresh_token'); - } - - if ($.inArray('offline_access', scopes) == -1) { - scopes.push("offline_access"); - } - - if (!$('disableRefreshTokenTimeout').is(':checked')) { - refreshTokenValiditySeconds = this.getFormTokenNumberValue($('#refreshTokenValidityTime input[type=text]').val(), $('#refreshTokenValidityTime select').val()); - } - } - - // make sure that the subject identifier is consistent with the redirect URIs - var subjectType = $('#subjectType input').filter(':checked').val(); - var redirectUris = this.redirectUrisCollection.pluck("item"); - var sectorIdentifierUri = $('#sectorIdentifierUri input').val(); - if (subjectType == 'PAIRWISE' && redirectUris.length > 1 && sectorIdentifierUri == '') { - //Display an alert with an error message - app.errorHandlerView.showErrorMessage($.t("client.client-form.error.consistency"), $.t("client.client-form.error.pairwise-sector")); + + previewLogo: function() { + if ($('#logoUri input', this.el).val()) { + $('#logoPreview', this.el).empty(); + $('#logoPreview', this.el).attr('src', $('#logoUri input', this.el).val()); + } else { + // $('#logoBlock', this.el).hide(); + $('#logoPreview', this.el).attr('src', 'resources/images/logo_placeholder.gif'); + } + }, + + /** + * Set up the form based on the current state of the tokenEndpointAuthMethod + * parameter + * + * @param event + */ + toggleClientCredentials: function() { + + var tokenEndpointAuthMethod = $('#tokenEndpointAuthMethod input', this.el).filter(':checked').val(); + + if (tokenEndpointAuthMethod == 'SECRET_BASIC' || tokenEndpointAuthMethod == 'SECRET_POST' || tokenEndpointAuthMethod == 'SECRET_JWT') { + + // client secret is required, show all the bits + $('#clientSecretPanel', this.el).show(); + // this function sets up the display portions + this.toggleGenerateClientSecret(); + } else { + // no client secret, hide all the bits + $('#clientSecretPanel', this.el).hide(); + } + + // show or hide the signing algorithm method depending on what's + // selected + if (tokenEndpointAuthMethod == 'PRIVATE_KEY' || tokenEndpointAuthMethod == 'SECRET_JWT') { + $('#tokenEndpointAuthSigningAlg', this.el).show(); + } else { + $('#tokenEndpointAuthSigningAlg', this.el).hide(); + } + }, + + /** + * Set up the form based on the JWK Set selector + */ + toggleJWKSetType: function() { + var jwkSelector = $('#jwkSelector input:radio', this.el).filter(':checked').val(); + + if (jwkSelector == 'URI') { + $('#jwksUri', this.el).show(); + $('#jwks', this.el).hide(); + } else if (jwkSelector == 'VAL') { + $('#jwksUri', this.el).hide(); + $('#jwks', this.el).show(); + } else { + $('#jwksUri', this.el).hide(); + $('#jwks', this.el).hide(); + } + + }, + + /** + * Set up the form based on the "Generate" checkbox + * + * @param event + */ + toggleGenerateClientSecret: function() { + + if ($('#generateClientSecret input', this.el).is(':checked')) { + // show the "generated" block, hide the "display" checkbox + $('#displayClientSecret', this.el).hide(); + $('#clientSecret', this.el).hide(); + $('#clientSecretGenerated', this.el).show(); + $('#clientSecretHidden', this.el).hide(); + } else { + // show the display checkbox, fall back to the "display" logic + $('#displayClientSecret', this.el).show(); + this.toggleDisplayClientSecret(); + } + }, + + /** + * Handle whether or not to display the client secret + * + * @param event + */ + toggleDisplayClientSecret: function() { + + if ($('#displayClientSecret input').is(':checked')) { + // want to display it + $('#clientSecret', this.el).show(); + $('#clientSecretHidden', this.el).hide(); + $('#clientSecretGenerated', this.el).hide(); + } else { + // want to hide it + $('#clientSecret', this.el).hide(); + $('#clientSecretHidden', this.el).show(); + $('#clientSecretGenerated', this.el).hide(); + } + }, + + // rounds down to the nearest integer value in seconds. + getFormTokenNumberValue: function(value, timeUnit) { + if (value == "") { + return null; + } else if (timeUnit == 'hours') { + return parseInt(parseFloat(value) * 3600); + } else if (timeUnit == 'minutes') { + return parseInt(parseFloat(value) * 60); + } else { // seconds + return parseInt(value); + } + }, + + // returns "null" if given the value "default" as a string, otherwise + // returns input value. useful for parsing the JOSE algorithm dropdowns + defaultToNull: function(value) { + if (value == 'default') { + return null; + } else { + return value; + } + }, + + // returns "null" if the given value is falsy + emptyToNull: function(value) { + if (value) { + return value; + } else { + return null; + } + }, + + disableUnsupportedJOSEItems: function(serverSupported, query) { + var supported = ['default']; + if (serverSupported) { + supported = _.union(supported, serverSupported); + } + $(query, this.$el).each(function(idx) { + if (_.contains(supported, $(this).val())) { + $(this).prop('disabled', false); + } else { + $(this).prop('disabled', true); + } + }); + + }, + + // maps from a form-friendly name to the real grant parameter name + grantMap: { + 'authorization_code': 'authorization_code', + 'password': 'password', + 'implicit': 'implicit', + 'client_credentials': 'client_credentials', + 'redelegate': 'urn:ietf:params:oauth:grant_type:redelegate', + 'refresh_token': 'refresh_token', + 'device': 'urn:ietf:params:oauth:grant-type:device_code' + }, + + // maps from a form-friendly name to the real response type parameter name + responseMap: { + 'code': 'code', + 'token': 'token', + 'idtoken': 'id_token', + 'token-idtoken': 'token id_token', + 'code-idtoken': 'code id_token', + 'code-token': 'code token', + 'code-token-idtoken': 'code token id_token' + }, + + saveClient: function(event) { + + $('.control-group').removeClass('error'); + + // sync any leftover collection items + _.each(this.listWidgetViews, function(v) { + v.addItem($.Event('click')); + }); + + // build the scope object + var scopes = this.scopeCollection.pluck("item"); + + // build the grant type object + var grantTypes = []; + $.each(this.grantMap, function(index, type) { + if ($('#grantTypes-' + index).is(':checked')) { + grantTypes.push(type); + } + }); + + // build the response type object + var responseTypes = []; + $.each(this.responseMap, function(index, type) { + if ($('#responseTypes-' + index).is(':checked')) { + responseTypes.push(type); + } + }); + + var generateClientSecret = $('#generateClientSecret input').is(':checked'); + var clientSecret = null; + + var tokenEndpointAuthMethod = $('#tokenEndpointAuthMethod input').filter(':checked').val(); + + // whether or not the client secret changed + var secretChanged = false; + + if (tokenEndpointAuthMethod == 'SECRET_BASIC' || tokenEndpointAuthMethod == 'SECRET_POST' || tokenEndpointAuthMethod == 'SECRET_JWT') { + + if (!generateClientSecret) { + // if it's required but we're not generating it, send the value + // to preserve it + clientSecret = $('#clientSecret input').val(); + + // if it's not the same as before, offer to display it + if (clientSecret != this.model.get('clientSecret')) { + secretChanged = true; + } + } else { + // it's being generated anew + secretChanged = true; + } + } + + var accessTokenValiditySeconds = null; + if (!$('disableAccessTokenTimeout').is(':checked')) { + accessTokenValiditySeconds = this.getFormTokenNumberValue($('#accessTokenValidityTime input[type=text]').val(), $('#accessTokenValidityTime select').val()); + } + + var idTokenValiditySeconds = this.getFormTokenNumberValue($('#idTokenValidityTime input[type=text]').val(), $('#idTokenValidityTime select').val()); + + var deviceCodeValiditySeconds = this.getFormTokenNumberValue($('#deviceCodeValidityTime input[type=text]').val(), $('#deviceCodeValidityTime select').val()); + + var refreshTokenValiditySeconds = null; + if ($('#allowRefresh').is(':checked')) { + + if ($.inArray('refresh_token', grantTypes) == -1) { + grantTypes.push('refresh_token'); + } + + if ($.inArray('offline_access', scopes) == -1) { + scopes.push("offline_access"); + } + + if (!$('disableRefreshTokenTimeout').is(':checked')) { + refreshTokenValiditySeconds = this.getFormTokenNumberValue($('#refreshTokenValidityTime input[type=text]').val(), $('#refreshTokenValidityTime select').val()); + } + } + + // make sure that the subject identifier is consistent with the redirect + // URIs + var subjectType = $('#subjectType input').filter(':checked').val(); + var redirectUris = this.redirectUrisCollection.pluck("item"); + var sectorIdentifierUri = $('#sectorIdentifierUri input').val(); + if (subjectType == 'PAIRWISE' && redirectUris.length > 1 && sectorIdentifierUri == '') { + // Display an alert with an error message + app.errorHandlerView.showErrorMessage($.t("client.client-form.error.consistency"), $.t("client.client-form.error.pairwise-sector")); return false; - - } - - // process the JWKS - var jwksUri = null; - var jwks = null; - var jwkSelector = $('#jwkSelector input:radio', this.el).filter(':checked').val(); - - if (jwkSelector == 'URI') { - jwksUri = $('#jwksUri input').val(); - jwks = null; - } else if (jwkSelector == 'VAL') { - jwksUri = null; - try { - jwks = JSON.parse($('#jwks textarea').val()); - } catch (e) { - console.log("An error occurred when parsing the JWK Set"); - app.errorHandlerView.showErrorMessage($.t("client.client-form.error.jwk-set"), $.t("client.client-form.error.jwk-set-parse")); - return false; - } - } else { - jwksUri = null; - jwks = null; - } - - - - var attrs = { - clientName:this.emptyToNull($('#clientName input').val()), - clientId:this.emptyToNull($('#clientId input').val()), - clientSecret: clientSecret, - generateClientSecret:generateClientSecret, - redirectUris: redirectUris, - clientDescription:this.emptyToNull($('#clientDescription textarea').val()), - logoUri:this.emptyToNull($('#logoUri input').val()), - grantTypes: grantTypes, - accessTokenValiditySeconds: accessTokenValiditySeconds, - refreshTokenValiditySeconds: refreshTokenValiditySeconds, - idTokenValiditySeconds: idTokenValiditySeconds, - deviceCodeValiditySeconds: deviceCodeValiditySeconds, - allowRefresh: $('#allowRefresh').is(':checked'), - allowIntrospection: $('#allowIntrospection input').is(':checked'), - scope: scopes, - tosUri: this.emptyToNull($('#tosUri input').val()), - policyUri: this.emptyToNull($('#policyUri input').val()), - clientUri: this.emptyToNull($('#clientUri input').val()), - applicationType: $('#applicationType input').filter(':checked').val(), - jwksUri: jwksUri, - jwks: jwks, - subjectType: subjectType, - softwareStatement: this.emptyToNull($('#softwareStatement textarea').val()), - softwareId: this.emptyToNull($('#softwareId input').val()), - softwareVersion: this.emptyToNull($('#softwareVersion input').val()), - tokenEndpointAuthMethod: tokenEndpointAuthMethod, - responseTypes: responseTypes, - sectorIdentifierUri: sectorIdentifierUri, - initiateLoginUri: this.emptyToNull($('#initiateLoginUri input').val()), - postLogoutRedirectUris: this.postLogoutRedirectUrisCollection.pluck('item'), - claimsRedirectUris: this.claimsRedirectUrisCollection.pluck('item'), - reuseRefreshToken: $('#reuseRefreshToken').is(':checked'), - clearAccessTokensOnRefresh: $('#clearAccessTokensOnRefresh').is(':checked'), - requireAuthTime: $('#requireAuthTime input').is(':checked'), - defaultMaxAge: parseInt($('#defaultMaxAge input').val()), - contacts: this.contactsCollection.pluck('item'), - requestUris: this.requestUrisCollection.pluck('item'), - defaultACRvalues: this.defaultACRvaluesCollection.pluck('item'), - requestObjectSigningAlg: this.defaultToNull($('#requestObjectSigningAlg select').val()), - userInfoSignedResponseAlg: this.defaultToNull($('#userInfoSignedResponseAlg select').val()), - userInfoEncryptedResponseAlg: this.defaultToNull($('#userInfoEncryptedResponseAlg select').val()), - userInfoEncryptedResponseEnc: this.defaultToNull($('#userInfoEncryptedResponseEnc select').val()), - idTokenSignedResponseAlg: this.defaultToNull($('#idTokenSignedResponseAlg select').val()), - idTokenEncryptedResponseAlg: this.defaultToNull($('#idTokenEncryptedResponseAlg select').val()), - idTokenEncryptedResponseEnc: this.defaultToNull($('#idTokenEncryptedResponseEnc select').val()), - tokenEndpointAuthSigningAlg: this.defaultToNull($('#tokenEndpointAuthSigningAlg select').val()), - codeChallengeMethod: this.defaultToNull($('#codeChallengeMethod select').val()) - }; - - // post-validate - if (attrs["allowRefresh"] == false) { - attrs["refreshTokenValiditySeconds"] = null; - } - - if ($('#disableAccessTokenTimeout').is(':checked')) { - attrs["accessTokenValiditySeconds"] = null; - } - - if ($('#disableRefreshTokenTimeout').is(':checked')) { - attrs["refreshTokenValiditySeconds"] = null; - } - - // set all empty strings to nulls - for (var key in attrs) { - if (attrs[key] === "") { - attrs[key] = null; - } - } - - var _self = this; - this.model.save(attrs, { - success:function () { - - $('#modalAlertLabel').html($.t('client.client-form.saved.saved')); - - var savedModel = { - clientId: _self.model.get('clientId'), - clientSecret: _self.model.get('clientSecret'), - secretChanged: secretChanged - }; - - $('#modalAlert div.modal-header').html($.t('client.client-form.saved.saved')); - - $('#modalAlert .modal-body').html(_self.clientSavedTemplate(savedModel)); - - $('#modalAlert .modal-body #savedClientSecret').hide(); - - $('#modalAlert').on('click', '#clientSaveShow', function(event) { - event.preventDefault(); - $('#clientSaveShow').hide(); - $('#savedClientSecret').show(); - }); - - $('#modalAlert').i18n(); - $('#modalAlert').modal({ - 'backdrop': 'static', - 'keyboard': true, - 'show': true - }); - - app.clientList.add(_self.model); - app.navigate('admin/clients', {trigger:true}); - }, - error:app.errorHandlerView.handleError({log: "An error occurred when saving a client"}) - }); - - return false; - }, - - render:function (eventName) { - - var data = {client: this.model.toJSON(), heartMode: heartMode}; - $(this.el).html(this.template(data)); - - var _self = this; - - // clear the sub-view collection - this.listWidgetViews = []; - - // build and bind registered redirect URI collection and view - _.each(this.model.get("redirectUris"), function (redirectUri) { - _self.redirectUrisCollection.add(new URIModel({item:redirectUri})); - }); - - - var redirUriView = new ListWidgetView({ - type:'uri', - placeholder: 'https://', - helpBlockText: $.t('client.client-form.redirect-uris-help'), - collection: this.redirectUrisCollection}); - $("#redirectUris .controls",this.el).html(redirUriView.render().el); - this.listWidgetViews.push(redirUriView); - - // build and bind scopes - _.each(this.model.get("scope"), function (scope) { - _self.scopeCollection.add(new Backbone.Model({item:scope})); - }); - - var scopeView = new ListWidgetView({ - placeholder: $.t('client.client-form.scope-placeholder'), - autocomplete: _.uniq(_.flatten(this.options.systemScopeList.pluck("value"))), - helpBlockText: $.t('client.client-form.scope-help'), - collection: this.scopeCollection}); - $("#scope .controls",this.el).html(scopeView.render().el); - this.listWidgetViews.push(scopeView); - - // build and bind contacts - _.each(this.model.get('contacts'), function (contact) { - _self.contactsCollection.add(new Backbone.Model({item:contact})); - }); - - var contactsView = new ListWidgetView({ - placeholder: $.t("client.client-form.contacts-placeholder"), - helpBlockText: $.t("client.client-form.contacts-help"), - collection: this.contactsCollection}); - $("#contacts .controls", this.el).html(contactsView.render().el); - this.listWidgetViews.push(contactsView); - - // build and bind post-logout redirect URIs - _.each(this.model.get('postLogoutRedirectUris'), function(postLogoutRedirectUri) { - _self.postLogoutRedirectUrisCollection.add(new URIModel({item:postLogoutRedirectUri})); - }); - - var postLogoutRedirectUrisView = new ListWidgetView({ - type: 'uri', - placeholder: 'https://', - helpBlockText: $.t('client.client-form.post-logout-help'), - collection: this.postLogoutRedirectUrisCollection}); - $('#postLogoutRedirectUris .controls', this.el).html(postLogoutRedirectUrisView.render().el); - this.listWidgetViews.push(postLogoutRedirectUrisView); - - // build and bind claims redirect URIs - _.each(this.model.get('claimsRedirectUris'), function(claimsRedirectUri) { - _self.claimsRedirectUrisCollection.add(new URIModel({item:claimsRedirectUri})); - }); - - var claimsRedirectUrisView = new ListWidgetView({ - type: 'uri', - placeholder: 'https://', - helpBlockText: $.t('client.client-form.claims-redirect-uris-help'), - collection: this.claimsRedirectUrisCollection}); - $('#claimsRedirectUris .controls', this.el).html(claimsRedirectUrisView.render().el); - this.listWidgetViews.push(claimsRedirectUrisView); - - // build and bind request URIs - _.each(this.model.get('requestUris'), function (requestUri) { - _self.requestUrisCollection.add(new URIModel({item:requestUri})); - }); - - var requestUriView = new ListWidgetView({ - type: 'uri', - placeholder: 'https://', - helpBlockText: $.t('client.client-form.request-uri-help'), - collection: this.requestUrisCollection}); - $('#requestUris .controls', this.el).html(requestUriView.render().el); - this.listWidgetViews.push(requestUriView); - - // build and bind default ACR values - _.each(this.model.get('defaultACRvalues'), function (defaultACRvalue) { - _self.defaultACRvaluesCollection.add(new Backbone.Model({item:defaultACRvalue})); - }); - - var defaultAcrView = new ListWidgetView({ - placeholder: $.t('client.client-form.acr-values-placeholder'), - // TODO: autocomplete from spec - helpBlockText: $.t('client.client-form.acr-values-help'), - collection: this.defaultACRvaluesCollection}); - $('#defaultAcrValues .controls', this.el).html(defaultAcrView.render().el); - this.listWidgetViews.push(defaultAcrView); - - // build and bind - - // set up token fields - if (!this.model.get("allowRefresh")) { - $("#refreshTokenValidityTime", this.$el).hide(); - } - - if (this.model.get("accessTokenValiditySeconds") == null) { - $("#access-token-timeout-time", this.$el).prop('disabled',true); - $("#access-token-timeout-unit", this.$el).prop('disabled',true); - } - - if (this.model.get("refreshTokenValiditySeconds") == null) { - $("#refresh-token-timeout-time", this.$el).prop('disabled',true); - $("#refresh-token-timeout-unit", this.$el).prop('disabled',true); - } - - // toggle other dynamic fields - this.toggleClientCredentials(); - this.previewLogo(); - this.toggleJWKSetType(); - - // disable unsupported JOSE algorithms - this.disableUnsupportedJOSEItems(app.serverConfiguration.request_object_signing_alg_values_supported, '#requestObjectSigningAlg option'); - this.disableUnsupportedJOSEItems(app.serverConfiguration.userinfo_signing_alg_values_supported, '#userInfoSignedResponseAlg option'); - this.disableUnsupportedJOSEItems(app.serverConfiguration.userinfo_encryption_alg_values_supported, '#userInfoEncryptedResponseAlg option'); - this.disableUnsupportedJOSEItems(app.serverConfiguration.userinfo_encryption_enc_values_supported, '#userInfoEncryptedResponseEnc option'); - this.disableUnsupportedJOSEItems(app.serverConfiguration.id_token_signing_alg_values_supported, '#idTokenSignedResponseAlg option'); - this.disableUnsupportedJOSEItems(app.serverConfiguration.id_token_encryption_alg_values_supported, '#idTokenEncryptedResponseAlg option'); - this.disableUnsupportedJOSEItems(app.serverConfiguration.id_token_encryption_enc_values_supported, '#idTokenEncryptedResponseEnc option'); - this.disableUnsupportedJOSEItems(app.serverConfiguration.token_endpoint_auth_signing_alg_values_supported, '#tokenEndpointAuthSigningAlg option'); - - this.$('.nyi').clickover({ - placement: 'right', - title: $.t('common.not-yet-implemented'), - content: $.t('common.not-yet-implemented-content') - }); - - $(this.el).i18n(); - return this; - } -}); + } + + // process the JWKS + var jwksUri = null; + var jwks = null; + var jwkSelector = $('#jwkSelector input:radio', this.el).filter(':checked').val(); + + if (jwkSelector == 'URI') { + jwksUri = $('#jwksUri input').val(); + jwks = null; + } else if (jwkSelector == 'VAL') { + jwksUri = null; + try { + jwks = JSON.parse($('#jwks textarea').val()); + } catch (e) { + console.log("An error occurred when parsing the JWK Set"); + app.errorHandlerView.showErrorMessage($.t("client.client-form.error.jwk-set"), $.t("client.client-form.error.jwk-set-parse")); + return false; + } + } else { + jwksUri = null; + jwks = null; + } + + var attrs = { + clientName: this.emptyToNull($('#clientName input').val()), + clientId: this.emptyToNull($('#clientId input').val()), + clientSecret: clientSecret, + generateClientSecret: generateClientSecret, + redirectUris: redirectUris, + clientDescription: this.emptyToNull($('#clientDescription textarea').val()), + logoUri: this.emptyToNull($('#logoUri input').val()), + grantTypes: grantTypes, + accessTokenValiditySeconds: accessTokenValiditySeconds, + refreshTokenValiditySeconds: refreshTokenValiditySeconds, + idTokenValiditySeconds: idTokenValiditySeconds, + deviceCodeValiditySeconds: deviceCodeValiditySeconds, + allowRefresh: $('#allowRefresh').is(':checked'), + allowIntrospection: $('#allowIntrospection input').is(':checked'), + scope: scopes, + tosUri: this.emptyToNull($('#tosUri input').val()), + policyUri: this.emptyToNull($('#policyUri input').val()), + clientUri: this.emptyToNull($('#clientUri input').val()), + applicationType: $('#applicationType input').filter(':checked').val(), + jwksUri: jwksUri, + jwks: jwks, + subjectType: subjectType, + softwareStatement: this.emptyToNull($('#softwareStatement textarea').val()), + softwareId: this.emptyToNull($('#softwareId input').val()), + softwareVersion: this.emptyToNull($('#softwareVersion input').val()), + tokenEndpointAuthMethod: tokenEndpointAuthMethod, + responseTypes: responseTypes, + sectorIdentifierUri: sectorIdentifierUri, + initiateLoginUri: this.emptyToNull($('#initiateLoginUri input').val()), + postLogoutRedirectUris: this.postLogoutRedirectUrisCollection.pluck('item'), + claimsRedirectUris: this.claimsRedirectUrisCollection.pluck('item'), + reuseRefreshToken: $('#reuseRefreshToken').is(':checked'), + clearAccessTokensOnRefresh: $('#clearAccessTokensOnRefresh').is(':checked'), + requireAuthTime: $('#requireAuthTime input').is(':checked'), + defaultMaxAge: parseInt($('#defaultMaxAge input').val()), + contacts: this.contactsCollection.pluck('item'), + requestUris: this.requestUrisCollection.pluck('item'), + defaultACRvalues: this.defaultACRvaluesCollection.pluck('item'), + requestObjectSigningAlg: this.defaultToNull($('#requestObjectSigningAlg select').val()), + userInfoSignedResponseAlg: this.defaultToNull($('#userInfoSignedResponseAlg select').val()), + userInfoEncryptedResponseAlg: this.defaultToNull($('#userInfoEncryptedResponseAlg select').val()), + userInfoEncryptedResponseEnc: this.defaultToNull($('#userInfoEncryptedResponseEnc select').val()), + idTokenSignedResponseAlg: this.defaultToNull($('#idTokenSignedResponseAlg select').val()), + idTokenEncryptedResponseAlg: this.defaultToNull($('#idTokenEncryptedResponseAlg select').val()), + idTokenEncryptedResponseEnc: this.defaultToNull($('#idTokenEncryptedResponseEnc select').val()), + tokenEndpointAuthSigningAlg: this.defaultToNull($('#tokenEndpointAuthSigningAlg select').val()), + codeChallengeMethod: this.defaultToNull($('#codeChallengeMethod select').val()) + }; + + // post-validate + if (attrs["allowRefresh"] == false) { + attrs["refreshTokenValiditySeconds"] = null; + } + + if ($('#disableAccessTokenTimeout').is(':checked')) { + attrs["accessTokenValiditySeconds"] = null; + } + + if ($('#disableRefreshTokenTimeout').is(':checked')) { + attrs["refreshTokenValiditySeconds"] = null; + } + + // set all empty strings to nulls + for ( var key in attrs) { + if (attrs[key] === "") { + attrs[key] = null; + } + } + + var _self = this; + this.model.save(attrs, { + success: function() { -ui.routes.push({path: "admin/clients", name: "listClients", callback: - function () { + $('#modalAlertLabel').html($.t('client.client-form.saved.saved')); - if (!isAdmin()) { - this.root(); - return; - } - - this.breadCrumbView.collection.reset(); - this.breadCrumbView.collection.add([ - {text:$.t('admin.home'), href:""}, - {text:$.t('client.manage'), href:"manage/#admin/clients"} - ]); - - this.updateSidebar('admin/clients'); + var savedModel = { + clientId: _self.model.get('clientId'), + clientSecret: _self.model.get('clientSecret'), + secretChanged: secretChanged + }; + + $('#modalAlert div.modal-header').html($.t('client.client-form.saved.saved')); + + $('#modalAlert .modal-body').html(_self.clientSavedTemplate(savedModel)); + + $('#modalAlert .modal-body #savedClientSecret').hide(); + + $('#modalAlert').on('click', '#clientSaveShow', function(event) { + event.preventDefault(); + $('#clientSaveShow').hide(); + $('#savedClientSecret').show(); + }); + + $('#modalAlert').i18n(); + $('#modalAlert').modal({ + 'backdrop': 'static', + 'keyboard': true, + 'show': true + }); + + app.clientList.add(_self.model); + app.navigate('admin/clients', { + trigger: true + }); + }, + error: app.errorHandlerView.handleError({ + log: "An error occurred when saving a client" + }) + }); + + return false; + }, - var view = new ClientListView({model:this.clientList, systemScopeList: this.systemScopeList, whiteListList: this.whiteListList}); - view.load(function() { - $('#content').html(view.render().el); - view.delegateEvents(); - setPageTitle($.t('client.manage')); - }); + render: function(eventName) { - } + var data = { + client: this.model.toJSON(), + heartMode: heartMode + }; + $(this.el).html(this.template(data)); + + var _self = this; + + // clear the sub-view collection + this.listWidgetViews = []; + + // build and bind registered redirect URI collection and view + _.each(this.model.get("redirectUris"), function(redirectUri) { + _self.redirectUrisCollection.add(new URIModel({ + item: redirectUri + })); + }); + + var redirUriView = new ListWidgetView({ + type: 'uri', + placeholder: 'https://', + helpBlockText: $.t('client.client-form.redirect-uris-help'), + collection: this.redirectUrisCollection + }); + $("#redirectUris .controls", this.el).html(redirUriView.render().el); + this.listWidgetViews.push(redirUriView); + + // build and bind scopes + _.each(this.model.get("scope"), function(scope) { + _self.scopeCollection.add(new Backbone.Model({ + item: scope + })); + }); + + var scopeView = new ListWidgetView({ + placeholder: $.t('client.client-form.scope-placeholder'), + autocomplete: _.uniq(_.flatten(this.options.systemScopeList.pluck("value"))), + helpBlockText: $.t('client.client-form.scope-help'), + collection: this.scopeCollection + }); + $("#scope .controls", this.el).html(scopeView.render().el); + this.listWidgetViews.push(scopeView); + + // build and bind contacts + _.each(this.model.get('contacts'), function(contact) { + _self.contactsCollection.add(new Backbone.Model({ + item: contact + })); + }); + + var contactsView = new ListWidgetView({ + placeholder: $.t("client.client-form.contacts-placeholder"), + helpBlockText: $.t("client.client-form.contacts-help"), + collection: this.contactsCollection + }); + $("#contacts .controls", this.el).html(contactsView.render().el); + this.listWidgetViews.push(contactsView); + + // build and bind post-logout redirect URIs + _.each(this.model.get('postLogoutRedirectUris'), function(postLogoutRedirectUri) { + _self.postLogoutRedirectUrisCollection.add(new URIModel({ + item: postLogoutRedirectUri + })); + }); + + var postLogoutRedirectUrisView = new ListWidgetView({ + type: 'uri', + placeholder: 'https://', + helpBlockText: $.t('client.client-form.post-logout-help'), + collection: this.postLogoutRedirectUrisCollection + }); + $('#postLogoutRedirectUris .controls', this.el).html(postLogoutRedirectUrisView.render().el); + this.listWidgetViews.push(postLogoutRedirectUrisView); + + // build and bind claims redirect URIs + _.each(this.model.get('claimsRedirectUris'), function(claimsRedirectUri) { + _self.claimsRedirectUrisCollection.add(new URIModel({ + item: claimsRedirectUri + })); + }); + + var claimsRedirectUrisView = new ListWidgetView({ + type: 'uri', + placeholder: 'https://', + helpBlockText: $.t('client.client-form.claims-redirect-uris-help'), + collection: this.claimsRedirectUrisCollection + }); + $('#claimsRedirectUris .controls', this.el).html(claimsRedirectUrisView.render().el); + this.listWidgetViews.push(claimsRedirectUrisView); + + // build and bind request URIs + _.each(this.model.get('requestUris'), function(requestUri) { + _self.requestUrisCollection.add(new URIModel({ + item: requestUri + })); + }); + + var requestUriView = new ListWidgetView({ + type: 'uri', + placeholder: 'https://', + helpBlockText: $.t('client.client-form.request-uri-help'), + collection: this.requestUrisCollection + }); + $('#requestUris .controls', this.el).html(requestUriView.render().el); + this.listWidgetViews.push(requestUriView); + + // build and bind default ACR values + _.each(this.model.get('defaultACRvalues'), function(defaultACRvalue) { + _self.defaultACRvaluesCollection.add(new Backbone.Model({ + item: defaultACRvalue + })); + }); + + var defaultAcrView = new ListWidgetView({ + placeholder: $.t('client.client-form.acr-values-placeholder'), + // TODO: autocomplete from spec + helpBlockText: $.t('client.client-form.acr-values-help'), + collection: this.defaultACRvaluesCollection + }); + $('#defaultAcrValues .controls', this.el).html(defaultAcrView.render().el); + this.listWidgetViews.push(defaultAcrView); + + // build and bind + + // set up token fields + if (!this.model.get("allowRefresh")) { + $("#refreshTokenValidityTime", this.$el).hide(); + } + + if (this.model.get("accessTokenValiditySeconds") == null) { + $("#access-token-timeout-time", this.$el).prop('disabled', true); + $("#access-token-timeout-unit", this.$el).prop('disabled', true); + } + + if (this.model.get("refreshTokenValiditySeconds") == null) { + $("#refresh-token-timeout-time", this.$el).prop('disabled', true); + $("#refresh-token-timeout-unit", this.$el).prop('disabled', true); + } + + // toggle other dynamic fields + this.toggleClientCredentials(); + this.previewLogo(); + this.toggleJWKSetType(); + + // disable unsupported JOSE algorithms + this.disableUnsupportedJOSEItems(app.serverConfiguration.request_object_signing_alg_values_supported, '#requestObjectSigningAlg option'); + this.disableUnsupportedJOSEItems(app.serverConfiguration.userinfo_signing_alg_values_supported, '#userInfoSignedResponseAlg option'); + this.disableUnsupportedJOSEItems(app.serverConfiguration.userinfo_encryption_alg_values_supported, '#userInfoEncryptedResponseAlg option'); + this.disableUnsupportedJOSEItems(app.serverConfiguration.userinfo_encryption_enc_values_supported, '#userInfoEncryptedResponseEnc option'); + this.disableUnsupportedJOSEItems(app.serverConfiguration.id_token_signing_alg_values_supported, '#idTokenSignedResponseAlg option'); + this.disableUnsupportedJOSEItems(app.serverConfiguration.id_token_encryption_alg_values_supported, '#idTokenEncryptedResponseAlg option'); + this.disableUnsupportedJOSEItems(app.serverConfiguration.id_token_encryption_enc_values_supported, '#idTokenEncryptedResponseEnc option'); + this.disableUnsupportedJOSEItems(app.serverConfiguration.token_endpoint_auth_signing_alg_values_supported, '#tokenEndpointAuthSigningAlg option'); + + this.$('.nyi').clickover({ + placement: 'right', + title: $.t('common.not-yet-implemented'), + content: $.t('common.not-yet-implemented-content') + }); + + $(this.el).i18n(); + return this; + } +}); + +ui.routes.push({ + path: "admin/clients", + name: "listClients", + callback: function() { + + if (!isAdmin()) { + this.root(); + return; + } + + this.breadCrumbView.collection.reset(); + this.breadCrumbView.collection.add([{ + text: $.t('admin.home'), + href: "" + }, { + text: $.t('client.manage'), + href: "manage/#admin/clients" + }]); + + this.updateSidebar('admin/clients'); + + var view = new ClientListView({ + model: this.clientList, + systemScopeList: this.systemScopeList, + whiteListList: this.whiteListList + }); + view.load(function() { + $('#content').html(view.render().el); + view.delegateEvents(); + setPageTitle($.t('client.manage')); + }); + + } }); -ui.routes.push({path: "admin/client/new", name: "newClient", callback: - function() { +ui.routes.push({ + path: "admin/client/new", + name: "newClient", + callback: function() { console.log("newClient"); if (!isAdmin()) { this.root(); return; } - - this.breadCrumbView.collection.reset(); - this.breadCrumbView.collection.add([ - {text:$.t('admin.home'), href:""}, - {text:$.t('client.manage'), href:"manage/#admin/clients"}, - {text:$.t('client.client-form.new'), href:""} - ]); - - this.updateSidebar('admin/clients'); - - var client = new ClientModel(); - - var view = new ClientFormView({model:client, systemScopeList: this.systemScopeList}); - view.load(function() { + + this.breadCrumbView.collection.reset(); + this.breadCrumbView.collection.add([{ + text: $.t('admin.home'), + href: "" + }, { + text: $.t('client.manage'), + href: "manage/#admin/clients" + }, { + text: $.t('client.client-form.new'), + href: "" + }]); + + this.updateSidebar('admin/clients'); + + var client = new ClientModel(); + + var view = new ClientFormView({ + model: client, + systemScopeList: this.systemScopeList + }); + view.load(function() { var userInfo = getUserInfo(); var contacts = []; if (userInfo != null && userInfo.email != null) { contacts.push(userInfo.email); } - + // use a different set of defaults based on heart mode flag if (heartMode) { - client.set({ - tokenEndpointAuthMethod: "PRIVATE_KEY", - generateClientSecret:false, - displayClientSecret:false, - requireAuthTime:true, - defaultMaxAge:60000, - scope: _.uniq(_.flatten(app.systemScopeList.defaultScopes().pluck("value"))), - accessTokenValiditySeconds:3600, - refreshTokenValiditySeconds:24*3600, - idTokenValiditySeconds:300, - deviceCodeValiditySeconds:30*60, - grantTypes: ["authorization_code"], - responseTypes: ["code"], - subjectType: "PUBLIC", - jwksType: "URI", - contacts: contacts - }, { silent: true }); + client.set({ + tokenEndpointAuthMethod: "PRIVATE_KEY", + generateClientSecret: false, + displayClientSecret: false, + requireAuthTime: true, + defaultMaxAge: 60000, + scope: _.uniq(_.flatten(app.systemScopeList.defaultScopes().pluck("value"))), + accessTokenValiditySeconds: 3600, + refreshTokenValiditySeconds: 24 * 3600, + idTokenValiditySeconds: 300, + deviceCodeValiditySeconds: 30 * 60, + grantTypes: ["authorization_code"], + responseTypes: ["code"], + subjectType: "PUBLIC", + jwksType: "URI", + contacts: contacts + }, { + silent: true + }); } else { - // set up this new client to require a secret and have us autogenerate one - client.set({ - tokenEndpointAuthMethod: "SECRET_BASIC", - generateClientSecret:true, - displayClientSecret:false, - requireAuthTime:true, - defaultMaxAge:60000, - scope: _.uniq(_.flatten(app.systemScopeList.defaultScopes().pluck("value"))), - accessTokenValiditySeconds:3600, - idTokenValiditySeconds:600, - deviceCodeValiditySeconds:30*60, - grantTypes: ["authorization_code"], - responseTypes: ["code"], - subjectType: "PUBLIC", - jwksType: "URI", - contacts: contacts - }, { silent: true }); + // set up this new client to require a secret and have us + // autogenerate one + client.set({ + tokenEndpointAuthMethod: "SECRET_BASIC", + generateClientSecret: true, + displayClientSecret: false, + requireAuthTime: true, + defaultMaxAge: 60000, + scope: _.uniq(_.flatten(app.systemScopeList.defaultScopes().pluck("value"))), + accessTokenValiditySeconds: 3600, + idTokenValiditySeconds: 600, + deviceCodeValiditySeconds: 30 * 60, + grantTypes: ["authorization_code"], + responseTypes: ["code"], + subjectType: "PUBLIC", + jwksType: "URI", + contacts: contacts + }, { + silent: true + }); } - - - $('#content').html(view.render().el); - setPageTitle($.t('client.client-form.new')); - }); + + $('#content').html(view.render().el); + setPageTitle($.t('client.client-form.new')); + }); } }); -ui.routes.push({path: "admin/client/:id", name: "editClient", callback: - function(id) { +ui.routes.push({ + path: "admin/client/:id", + name: "editClient", + callback: function(id) { console.log("editClient " + id); if (!isAdmin()) { this.root(); return; } - - this.breadCrumbView.collection.reset(); - this.breadCrumbView.collection.add([ - {text:$.t('admin.home'), href:""}, - {text:$.t('client.manage'), href:"manage/#admin/clients"}, - {text:$.t('client.client-form.edit'), href:"manage/#admin/client/" + id} - ]); - - this.updateSidebar('admin/clients'); - - var client = this.clientList.get(id); - if (!client) { - client = new ClientModel({id:id}); - } - - var view = new ClientFormView({model:client, systemScopeList: app.systemScopeList}); - view.load(function() { - if ($.inArray("refresh_token", client.get("grantTypes")) != -1) { - client.set({ - allowRefresh: true - }, { silent: true }); - } - - if (client.get("jwks")) { - client.set({ - jwksType: "VAL" - }, { silent: true }); - } else { - client.set({ - jwksType: "URI" - }, { silent: true }); - } - - client.set({ - generateClientSecret:false, - displayClientSecret:false - }, { silent: true }); - - $('#content').html(view.render().el); - setPageTitle($.t('client.client-form.edit')); - }); - + + this.breadCrumbView.collection.reset(); + this.breadCrumbView.collection.add([{ + text: $.t('admin.home'), + href: "" + }, { + text: $.t('client.manage'), + href: "manage/#admin/clients" + }, { + text: $.t('client.client-form.edit'), + href: "manage/#admin/client/" + id + }]); + + this.updateSidebar('admin/clients'); + + var client = this.clientList.get(id); + if (!client) { + client = new ClientModel({ + id: id + }); + } + + var view = new ClientFormView({ + model: client, + systemScopeList: app.systemScopeList + }); + view.load(function() { + if ($.inArray("refresh_token", client.get("grantTypes")) != -1) { + client.set({ + allowRefresh: true + }, { + silent: true + }); + } + + if (client.get("jwks")) { + client.set({ + jwksType: "VAL" + }, { + silent: true + }); + } else { + client.set({ + jwksType: "URI" + }, { + silent: true + }); + } + + client.set({ + generateClientSecret: false, + displayClientSecret: false + }, { + silent: true + }); + + $('#content').html(view.render().el); + setPageTitle($.t('client.client-form.edit')); + }); + } }); ui.templates.push('resources/template/client.html'); ui.init.push(function(app) { - app.clientList = new ClientCollection(); + app.clientList = new ClientCollection(); }); diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/dynreg.js b/openid-connect-server-webapp/src/main/webapp/resources/js/dynreg.js index dca9fe2f25..81b052a916 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/dynreg.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/dynreg.js @@ -15,713 +15,816 @@ * limitations under the License. *******************************************************************************/ var DynRegClient = Backbone.Model.extend({ - idAttribute: "client_id", - - defaults:{ - client_id:null, - client_secret:null, - redirect_uris:[], - client_name:null, - client_uri:null, - logo_uri:null, - contacts:[], - tos_uri:null, - token_endpoint_auth_method:null, - scope:null, - grant_types:[], - response_types:[], - policy_uri:null, - - jwks_uri:null, - jwks:null, - jwksType:'URI', - - application_type:null, - sector_identifier_uri:null, - subject_type:null, - - request_object_signing_alg:null, - - userinfo_signed_response_alg:null, - userinfo_encrypted_response_alg:null, - userinfo_encrypted_response_enc:null, - - id_token_signed_response_alg:null, - id_token_encrypted_response_alg:null, - id_token_encrypted_response_enc:null, - - default_max_age:null, - require_auth_time:false, - default_acr_values:null, - - initiate_login_uri:null, - post_logout_redirect_uris:null, - - claims_redirect_uris:[], - - request_uris:[], - - software_statement:null, - software_id:null, - software_version:null, - - code_challenge_method:null, - - registration_access_token:null, - registration_client_uri:null - }, - - sync: function(method, model, options){ - if (model.get('registration_access_token')) { - var headers = options.headers ? options.headers : {}; - headers['Authorization'] = 'Bearer ' + model.get('registration_access_token'); - options.headers = headers; - } - - return this.constructor.__super__.sync(method, model, options); - }, - - urlRoot:'register' - + idAttribute: "client_id", + + defaults: { + client_id: null, + client_secret: null, + redirect_uris: [], + client_name: null, + client_uri: null, + logo_uri: null, + contacts: [], + tos_uri: null, + token_endpoint_auth_method: null, + scope: null, + grant_types: [], + response_types: [], + policy_uri: null, + + jwks_uri: null, + jwks: null, + jwksType: 'URI', + + application_type: null, + sector_identifier_uri: null, + subject_type: null, + + request_object_signing_alg: null, + + userinfo_signed_response_alg: null, + userinfo_encrypted_response_alg: null, + userinfo_encrypted_response_enc: null, + + id_token_signed_response_alg: null, + id_token_encrypted_response_alg: null, + id_token_encrypted_response_enc: null, + + default_max_age: null, + require_auth_time: false, + default_acr_values: null, + + initiate_login_uri: null, + post_logout_redirect_uris: null, + + claims_redirect_uris: [], + + request_uris: [], + + software_statement: null, + software_id: null, + software_version: null, + + code_challenge_method: null, + + registration_access_token: null, + registration_client_uri: null + }, + + sync: function(method, model, options) { + if (model.get('registration_access_token')) { + var headers = options.headers ? options.headers : {}; + headers['Authorization'] = 'Bearer ' + model.get('registration_access_token'); + options.headers = headers; + } + + return this.constructor.__super__.sync(method, model, options); + }, + + urlRoot: 'register' + }); var DynRegRootView = Backbone.View.extend({ - + tagName: 'span', - - initialize:function(options) { - this.options = options; - + + initialize: function(options) { + this.options = options; + }, - - events:{ - "click #newreg":"newReg", - "click #editreg":"editReg" + + events: { + "click #newreg": "newReg", + "click #editreg": "editReg" }, - - load:function(callback) { - if (this.options.systemScopeList.isFetched) { - callback(); - return; - } - - $('#loadingbox').sheet('show'); - $('#loading').html('' + $.t('common.scopes') + ' '); - - $.when(this.options.systemScopeList.fetchIfNeeded({success:function(e) {$('#loading-scopes').addClass('label-success');}, error:app.errorHandlerView.handleError()})) - .done(function() { - $('#loadingbox').sheet('hide'); - callback(); - }); + + load: function(callback) { + if (this.options.systemScopeList.isFetched) { + callback(); + return; + } + + $('#loadingbox').sheet('show'); + $('#loading').html('' + $.t('common.scopes') + ' '); + + $.when(this.options.systemScopeList.fetchIfNeeded({ + success: function(e) { + $('#loading-scopes').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + })).done(function() { + $('#loadingbox').sheet('hide'); + callback(); + }); }, - - render:function() { - $(this.el).html($('#tmpl-dynreg').html()); - $(this.el).i18n(); - return this; + + render: function() { + $(this.el).html($('#tmpl-dynreg').html()); + $(this.el).i18n(); + return this; }, - - newReg:function(e) { - e.preventDefault(); - this.remove(); - app.navigate('dev/dynreg/new', {trigger: true}); + + newReg: function(e) { + e.preventDefault(); + this.remove(); + app.navigate('dev/dynreg/new', { + trigger: true + }); }, - - editReg:function(e) { - e.preventDefault(); + + editReg: function(e) { + e.preventDefault(); var clientId = $('#clientId').val(); var token = $('#regtoken').val(); - + var client = new DynRegClient({ client_id: clientId, registration_access_token: token }); - + var self = this; - + client.fetch({ success: function() { - var userInfo = getUserInfo(); - var contacts = client.get("contacts"); - if (userInfo != null && userInfo.email != null && ! _.contains(contacts, userInfo.email)) { - contacts.push(userInfo.email); - } - client.set({ - contacts: contacts - }, { silent: true }); - - if (client.get("jwks")) { - client.set({ - jwksType: "VAL" - }, { silent: true }); - } else { - client.set({ - jwksType: "URI" - }, { silent: true }); - } - - var view = new DynRegEditView({model: client, systemScopeList: app.systemScopeList}); - - view.load(function() { - $('#content').html(view.render().el); - view.delegateEvents(); - setPageTitle($.t('dynreg.edit-dynamically-registered')); - app.navigate('dev/dynreg/edit', {trigger: true}); - self.remove(); - }); - }, error:app.errorHandlerView.handleError({message: $.t('dynreg.invalid-access-token')}) + var userInfo = getUserInfo(); + var contacts = client.get("contacts"); + if (userInfo != null && userInfo.email != null && !_.contains(contacts, userInfo.email)) { + contacts.push(userInfo.email); + } + client.set({ + contacts: contacts + }, { + silent: true + }); + + if (client.get("jwks")) { + client.set({ + jwksType: "VAL" + }, { + silent: true + }); + } else { + client.set({ + jwksType: "URI" + }, { + silent: true + }); + } + + var view = new DynRegEditView({ + model: client, + systemScopeList: app.systemScopeList + }); + + view.load(function() { + $('#content').html(view.render().el); + view.delegateEvents(); + setPageTitle($.t('dynreg.edit-dynamically-registered')); + app.navigate('dev/dynreg/edit', { + trigger: true + }); + self.remove(); + }); + }, + error: app.errorHandlerView.handleError({ + message: $.t('dynreg.invalid-access-token') + }) }); } - + }); var DynRegEditView = Backbone.View.extend({ - + tagName: 'span', - - initialize:function(options) { - this.options = options; - if (!this.template) { - this.template = _.template($('#tmpl-dynreg-client-form').html()); - } - - this.redirectUrisCollection = new Backbone.Collection(); - this.scopeCollection = new Backbone.Collection(); - this.contactsCollection = new Backbone.Collection(); - this.defaultAcrValuesCollection = new Backbone.Collection(); - this.requestUrisCollection = new Backbone.Collection(); - this.postLogoutRedirectUrisCollection = new Backbone.Collection(); - this.claimsRedirectUrisCollection = new Backbone.Collection(); - - this.listWidgetViews = []; + + initialize: function(options) { + this.options = options; + if (!this.template) { + this.template = _.template($('#tmpl-dynreg-client-form').html()); + } + + this.redirectUrisCollection = new Backbone.Collection(); + this.scopeCollection = new Backbone.Collection(); + this.contactsCollection = new Backbone.Collection(); + this.defaultAcrValuesCollection = new Backbone.Collection(); + this.requestUrisCollection = new Backbone.Collection(); + this.postLogoutRedirectUrisCollection = new Backbone.Collection(); + this.claimsRedirectUrisCollection = new Backbone.Collection(); + + this.listWidgetViews = []; + }, + + load: function(callback) { + if (this.options.systemScopeList.isFetched) { + callback(); + return; + } + + $('#loadingbox').sheet('show'); + $('#loading').html('' + $.t('common.scopes') + ' '); + + $.when(this.options.systemScopeList.fetchIfNeeded({ + success: function(e) { + $('#loading-scopes').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + })).done(function() { + $('#loadingbox').sheet('hide'); + callback(); + }); + }, + + events: { + "click .btn-save": "saveClient", + "click .btn-cancel": "cancel", + "click .btn-delete": "deleteClient", + "change #logoUri input": "previewLogo", + "change #tokenEndpointAuthMethod input:radio": "toggleClientCredentials", + "change #jwkSelector input:radio": "toggleJWKSetType" + }, + + cancel: function(e) { + e.preventDefault(); + app.navigate('dev/dynreg', { + trigger: true + }); + }, + + deleteClient: function(e) { + e.preventDefault(); + + if (confirm($.t('client.client-table.confirm'))) { + var self = this; + + this.model.destroy({ + dataType: false, + processData: false, + success: function() { + self.remove(); + app.navigate('dev/dynreg', { + trigger: true + }); + }, + error: app.errorHandlerView.handleError({ + "log": "An error occurred when deleting a client" + }) + }); + + } + + return false; + }, + + previewLogo: function() { + if ($('#logoUri input', this.el).val()) { + $('#logoPreview', this.el).empty(); + $('#logoPreview', this.el).attr('src', $('#logoUri input', this.el).val()); + } else { + // $('#logoBlock', this.el).hide(); + $('#logoPreview', this.el).attr('src', 'resources/images/logo_placeholder.gif'); + } }, - - load:function(callback) { - if (this.options.systemScopeList.isFetched) { - callback(); - return; - } - - $('#loadingbox').sheet('show'); - $('#loading').html('' + $.t('common.scopes') + ' '); - - $.when(this.options.systemScopeList.fetchIfNeeded({success:function(e) {$('#loading-scopes').addClass('label-success');}, error:app.errorHandlerView.handleError()})) - .done(function() { - $('#loadingbox').sheet('hide'); - callback(); - }); + + /** + * Set up the form based on the current state of the tokenEndpointAuthMethod + * parameter + * + * @param event + */ + toggleClientCredentials: function() { + + var tokenEndpointAuthMethod = $('#tokenEndpointAuthMethod input', this.el).filter(':checked').val(); + + // show or hide the signing algorithm method depending on what's + // selected + if (tokenEndpointAuthMethod == 'private_key_jwt' || tokenEndpointAuthMethod == 'client_secret_jwt') { + $('#tokenEndpointAuthSigningAlg', this.el).show(); + } else { + $('#tokenEndpointAuthSigningAlg', this.el).hide(); + } }, - - events:{ - "click .btn-save":"saveClient", - "click .btn-cancel":"cancel", - "click .btn-delete":"deleteClient", - "change #logoUri input":"previewLogo", - "change #tokenEndpointAuthMethod input:radio":"toggleClientCredentials", - "change #jwkSelector input:radio":"toggleJWKSetType" - }, - - cancel:function(e) { - e.preventDefault(); - app.navigate('dev/dynreg', {trigger: true}); - }, - - deleteClient:function (e) { - e.preventDefault(); - - if (confirm($.t('client.client-table.confirm'))) { - var self = this; - - this.model.destroy({ - dataType: false, processData: false, - success:function () { - self.remove(); - app.navigate('dev/dynreg', {trigger: true}); - }, - error:app.errorHandlerView.handleError({"log": "An error occurred when deleting a client"}) - }); - - } - - return false; - }, - - previewLogo:function() { - if ($('#logoUri input', this.el).val()) { - $('#logoPreview', this.el).empty(); - $('#logoPreview', this.el).attr('src', $('#logoUri input', this.el).val()); - } else { - //$('#logoBlock', this.el).hide(); - $('#logoPreview', this.el).attr('src', 'resources/images/logo_placeholder.gif'); - } - }, - - /** - * Set up the form based on the current state of the tokenEndpointAuthMethod parameter - * @param event - */ - toggleClientCredentials:function() { - - var tokenEndpointAuthMethod = $('#tokenEndpointAuthMethod input', this.el).filter(':checked').val(); - - // show or hide the signing algorithm method depending on what's selected - if (tokenEndpointAuthMethod == 'private_key_jwt' - || tokenEndpointAuthMethod == 'client_secret_jwt') { - $('#tokenEndpointAuthSigningAlg', this.el).show(); - } else { - $('#tokenEndpointAuthSigningAlg', this.el).hide(); - } - }, - - /** - * Set up the form based on the JWK Set selector - */ - toggleJWKSetType:function() { - var jwkSelector = $('#jwkSelector input:radio', this.el).filter(':checked').val(); - - if (jwkSelector == 'URI') { - $('#jwksUri', this.el).show(); - $('#jwks', this.el).hide(); - } else if (jwkSelector == 'VAL') { - $('#jwksUri', this.el).hide(); - $('#jwks', this.el).show(); - } else { - $('#jwksUri', this.el).hide(); - $('#jwks', this.el).hide(); - } - - }, - - disableUnsupportedJOSEItems:function(serverSupported, query) { - var supported = ['default']; - if (serverSupported) { - supported = _.union(supported, serverSupported); - } - $(query, this.$el).each(function(idx) { - if(_.contains(supported, $(this).val())) { - $(this).prop('disabled', false); - } else { - $(this).prop('disabled', true); - } - }); - - }, - - // returns "null" if given the value "default" as a string, otherwise returns input value. useful for parsing the JOSE algorithm dropdowns - defaultToNull:function(value) { - if (value == 'default') { - return null; - } else { - return value; - } - }, - - // returns "null" if the given value is falsy - emptyToNull:function(value) { - if (value) { - return value; - } else { - return null; - } - }, - - // maps from a form-friendly name to the real grant parameter name - grantMap:{ - 'authorization_code': 'authorization_code', - 'password': 'password', - 'implicit': 'implicit', - 'client_credentials': 'client_credentials', - 'redelegate': 'urn:ietf:params:oauth:grant_type:redelegate', - 'refresh_token': 'refresh_token' - }, - - // maps from a form-friendly name to the real response type parameter name - responseMap:{ - 'code': 'code', - 'token': 'token', - 'idtoken': 'id_token', - 'token-idtoken': 'token id_token', - 'code-idtoken': 'code id_token', - 'code-token': 'code token', - 'code-token-idtoken': 'code token id_token' - }, - - saveClient:function (e) { - e.preventDefault(); - - $('.control-group').removeClass('error'); - - // sync any leftover collection items - _.each(this.listWidgetViews, function(v) { - v.addItem($.Event('click')); - }); - - // build the scope object - var scopes = this.scopeCollection.pluck("item").join(" "); - - // build the grant type object - var grantTypes = []; - $.each(this.grantMap, function(index,type) { - if ($('#grantTypes-' + index).is(':checked')) { - grantTypes.push(type); - } - }); - - // build the response type object - var responseTypes = []; - $.each(this.responseMap, function(index,type) { - if ($('#responseTypes-' + index).is(':checked')) { - responseTypes.push(type); - } - }); - - var contacts = this.contactsCollection.pluck('item'); - var userInfo = getUserInfo(); - if (userInfo && userInfo.email) { - if (!_.contains(contacts, userInfo.email)) { - contacts.push(userInfo.email); - } - } - - // make sure that the subject identifier is consistent with the redirect URIs - var subjectType = $('#subjectType input').filter(':checked').val(); - var redirectUris = this.redirectUrisCollection.pluck("item"); - var sectorIdentifierUri = $('#sectorIdentifierUri input').val(); - if (subjectType == 'PAIRWISE' && redirectUris.length > 1 && sectorIdentifierUri == '') { - //Display an alert with an error message - app.errorHandlerView.showErrorMessage($.t("client.client-form.error.consistency"), $.t("client.client-form.error.pairwise-sector")); + + /** + * Set up the form based on the JWK Set selector + */ + toggleJWKSetType: function() { + var jwkSelector = $('#jwkSelector input:radio', this.el).filter(':checked').val(); + + if (jwkSelector == 'URI') { + $('#jwksUri', this.el).show(); + $('#jwks', this.el).hide(); + } else if (jwkSelector == 'VAL') { + $('#jwksUri', this.el).hide(); + $('#jwks', this.el).show(); + } else { + $('#jwksUri', this.el).hide(); + $('#jwks', this.el).hide(); + } + + }, + + disableUnsupportedJOSEItems: function(serverSupported, query) { + var supported = ['default']; + if (serverSupported) { + supported = _.union(supported, serverSupported); + } + $(query, this.$el).each(function(idx) { + if (_.contains(supported, $(this).val())) { + $(this).prop('disabled', false); + } else { + $(this).prop('disabled', true); + } + }); + + }, + + // returns "null" if given the value "default" as a string, + // otherwise returns input value. useful for parsing the JOSE + // algorithm dropdowns + defaultToNull: function(value) { + if (value == 'default') { + return null; + } else { + return value; + } + }, + + // returns "null" if the given value is falsy + emptyToNull: function(value) { + if (value) { + return value; + } else { + return null; + } + }, + + // maps from a form-friendly name to the real grant parameter name + grantMap: { + 'authorization_code': 'authorization_code', + 'password': 'password', + 'implicit': 'implicit', + 'client_credentials': 'client_credentials', + 'redelegate': 'urn:ietf:params:oauth:grant_type:redelegate', + 'refresh_token': 'refresh_token' + }, + + // maps from a form-friendly name to the real response type + // parameter name + responseMap: { + 'code': 'code', + 'token': 'token', + 'idtoken': 'id_token', + 'token-idtoken': 'token id_token', + 'code-idtoken': 'code id_token', + 'code-token': 'code token', + 'code-token-idtoken': 'code token id_token' + }, + + saveClient: function(e) { + e.preventDefault(); + + $('.control-group').removeClass('error'); + + // sync any leftover collection items + _.each(this.listWidgetViews, function(v) { + v.addItem($.Event('click')); + }); + + // build the scope object + var scopes = this.scopeCollection.pluck("item").join(" "); + + // build the grant type object + var grantTypes = []; + $.each(this.grantMap, function(index, type) { + if ($('#grantTypes-' + index).is(':checked')) { + grantTypes.push(type); + } + }); + + // build the response type object + var responseTypes = []; + $.each(this.responseMap, function(index, type) { + if ($('#responseTypes-' + index).is(':checked')) { + responseTypes.push(type); + } + }); + + var contacts = this.contactsCollection.pluck('item'); + var userInfo = getUserInfo(); + if (userInfo && userInfo.email) { + if (!_.contains(contacts, userInfo.email)) { + contacts.push(userInfo.email); + } + } + + // make sure that the subject identifier is consistent with the + // redirect URIs + var subjectType = $('#subjectType input').filter(':checked').val(); + var redirectUris = this.redirectUrisCollection.pluck("item"); + var sectorIdentifierUri = $('#sectorIdentifierUri input').val(); + if (subjectType == 'PAIRWISE' && redirectUris.length > 1 && sectorIdentifierUri == '') { + // Display an alert with an error message + app.errorHandlerView.showErrorMessage($.t("client.client-form.error.consistency"), $.t("client.client-form.error.pairwise-sector")); return false; - - } - - // process the JWKS - var jwksUri = null; - var jwks = null; - var jwkSelector = $('#jwkSelector input:radio', this.el).filter(':checked').val(); - - if (jwkSelector == 'URI') { - jwksUri = $('#jwksUri input').val(); - jwks = null; - } else if (jwkSelector == 'VAL') { - jwksUri = null; - try { - jwks = JSON.parse($('#jwks textarea').val()); - } catch (e) { - console.log("An error occurred when parsing the JWK Set"); - app.errorHandlerView.showErrorMessage($.t("client.client-form.error.jwk-set"), $.t("client.client-form.error.jwk-set-parse")); - return false; - } - } else { - jwksUri = null; - jwks = null; - } - - var attrs = { - client_name:this.emptyToNull($('#clientName input').val()), - redirect_uris: redirectUris, - logo_uri:this.emptyToNull($('#logoUri input').val()), - grant_types: grantTypes, - scope: scopes, - client_secret: null, // never send a client secret - tos_uri: this.emptyToNull($('#tosUri input').val()), - policy_uri: this.emptyToNull($('#policyUri input').val()), - client_uri: this.emptyToNull($('#clientUri input').val()), - application_type: $('#applicationType input').filter(':checked').val(), - jwks_uri: jwksUri, - jwks: jwks, - subject_type: subjectType, - software_statement: this.emptyToNull($('#softwareStatement textarea').val()), - softwareId: this.emptyToNull($('#softwareId input').val()), - softwareVersion: this.emptyToNull($('#softwareVersion input').val()), - token_endpoint_auth_method: $('#tokenEndpointAuthMethod input').filter(':checked').val(), - response_types: responseTypes, - sector_identifier_uri: sectorIdentifierUri, - initiate_login_uri: this.emptyToNull($('#initiateLoginUri input').val()), - post_logout_redirect_uris: this.postLogoutRedirectUrisCollection.pluck('item'), - claims_redirect_uris: this.claimsRedirectUrisCollection.pluck('item'), - require_auth_time: $('#requireAuthTime input').is(':checked'), - default_max_age: parseInt($('#defaultMaxAge input').val()), - contacts: contacts, - request_uris: this.requestUrisCollection.pluck('item'), - default_acr_values: this.defaultAcrValuesCollection.pluck('item'), - request_object_signing_alg: this.defaultToNull($('#requestObjectSigningAlg select').val()), - userinfo_signed_response_alg: this.defaultToNull($('#userInfoSignedResponseAlg select').val()), - userinfo_encrypted_response_alg: this.defaultToNull($('#userInfoEncryptedResponseAlg select').val()), - userinfo_encrypted_response_enc: this.defaultToNull($('#userInfoEncryptedResponseEnc select').val()), - id_token_signed_response_alg: this.defaultToNull($('#idTokenSignedResponseAlg select').val()), - id_token_encrypted_response_alg: this.defaultToNull($('#idTokenEncryptedResponseAlg select').val()), - id_token_encrypted_response_enc: this.defaultToNull($('#idTokenEncryptedResponseEnc select').val()), - token_endpoint_auth_signing_alg: this.defaultToNull($('#tokenEndpointAuthSigningAlg select').val()), - code_challenge_method: this.defaultToNull($('#codeChallengeMethod select').val()) - }; - - // set all empty strings to nulls - for (var key in attrs) { - if (attrs[key] === "") { - attrs[key] = null; - } - } - - var _self = this; - this.model.save(attrs, { - success:function () { - // switch to an "edit" view - app.navigate('dev/dynreg/edit', {trigger: true}); - _self.remove(); - - var userInfo = getUserInfo(); - var contacts = _self.model.get("contacts"); - if (userInfo != null && userInfo.email != null && ! _.contains(contacts, userInfo.email)) { - contacts.push(userInfo.email); - } - _self.model.set({ - contacts: contacts - }, { silent: true }); - - if (_self.model.get("jwks")) { - _self.model.set({ - jwksType: "VAL" - }, { silent: true }); - } else { - _self.model.set({ - jwksType: "URI" - }, { silent: true }); - } - - var view = new DynRegEditView({model: _self.model, systemScopeList: _self.options.systemScopeList}); - - view.load(function() { - // reload - $('#content').html(view.render().el); - view.delegateEvents(); - }); - }, - error:app.errorHandlerView.handleError({log: "An error occurred when saving a client"}) - }); - - return false; - }, - - render:function() { - var data = {client: this.model.toJSON(), userInfo: getUserInfo(), heartMode: heartMode}; + + } + + // process the JWKS + var jwksUri = null; + var jwks = null; + var jwkSelector = $('#jwkSelector input:radio', this.el).filter(':checked').val(); + + if (jwkSelector == 'URI') { + jwksUri = $('#jwksUri input').val(); + jwks = null; + } else if (jwkSelector == 'VAL') { + jwksUri = null; + try { + jwks = JSON.parse($('#jwks textarea').val()); + } catch (e) { + console.log("An error occurred when parsing the JWK Set"); + app.errorHandlerView.showErrorMessage($.t("client.client-form.error.jwk-set"), $.t("client.client-form.error.jwk-set-parse")); + return false; + } + } else { + jwksUri = null; + jwks = null; + } + + var attrs = { + client_name: this.emptyToNull($('#clientName input').val()), + redirect_uris: redirectUris, + logo_uri: this.emptyToNull($('#logoUri input').val()), + grant_types: grantTypes, + scope: scopes, + client_secret: null, // never send a client secret + tos_uri: this.emptyToNull($('#tosUri input').val()), + policy_uri: this.emptyToNull($('#policyUri input').val()), + client_uri: this.emptyToNull($('#clientUri input').val()), + application_type: $('#applicationType input').filter(':checked').val(), + jwks_uri: jwksUri, + jwks: jwks, + subject_type: subjectType, + software_statement: this.emptyToNull($('#softwareStatement textarea').val()), + softwareId: this.emptyToNull($('#softwareId input').val()), + softwareVersion: this.emptyToNull($('#softwareVersion input').val()), + token_endpoint_auth_method: $('#tokenEndpointAuthMethod input').filter(':checked').val(), + response_types: responseTypes, + sector_identifier_uri: sectorIdentifierUri, + initiate_login_uri: this.emptyToNull($('#initiateLoginUri input').val()), + post_logout_redirect_uris: this.postLogoutRedirectUrisCollection.pluck('item'), + claims_redirect_uris: this.claimsRedirectUrisCollection.pluck('item'), + require_auth_time: $('#requireAuthTime input').is(':checked'), + default_max_age: parseInt($('#defaultMaxAge input').val()), + contacts: contacts, + request_uris: this.requestUrisCollection.pluck('item'), + default_acr_values: this.defaultAcrValuesCollection.pluck('item'), + request_object_signing_alg: this.defaultToNull($('#requestObjectSigningAlg select').val()), + userinfo_signed_response_alg: this.defaultToNull($('#userInfoSignedResponseAlg select').val()), + userinfo_encrypted_response_alg: this.defaultToNull($('#userInfoEncryptedResponseAlg select').val()), + userinfo_encrypted_response_enc: this.defaultToNull($('#userInfoEncryptedResponseEnc select').val()), + id_token_signed_response_alg: this.defaultToNull($('#idTokenSignedResponseAlg select').val()), + id_token_encrypted_response_alg: this.defaultToNull($('#idTokenEncryptedResponseAlg select').val()), + id_token_encrypted_response_enc: this.defaultToNull($('#idTokenEncryptedResponseEnc select').val()), + token_endpoint_auth_signing_alg: this.defaultToNull($('#tokenEndpointAuthSigningAlg select').val()), + code_challenge_method: this.defaultToNull($('#codeChallengeMethod select').val()) + }; + + // set all empty strings to nulls + for ( var key in attrs) { + if (attrs[key] === "") { + attrs[key] = null; + } + } + + var _self = this; + this.model.save(attrs, { + success: function() { + // switch to an "edit" view + app.navigate('dev/dynreg/edit', { + trigger: true + }); + _self.remove(); + + var userInfo = getUserInfo(); + var contacts = _self.model.get("contacts"); + if (userInfo != null && userInfo.email != null && !_.contains(contacts, userInfo.email)) { + contacts.push(userInfo.email); + } + _self.model.set({ + contacts: contacts + }, { + silent: true + }); + + if (_self.model.get("jwks")) { + _self.model.set({ + jwksType: "VAL" + }, { + silent: true + }); + } else { + _self.model.set({ + jwksType: "URI" + }, { + silent: true + }); + } + + var view = new DynRegEditView({ + model: _self.model, + systemScopeList: _self.options.systemScopeList + }); + + view.load(function() { + // reload + $('#content').html(view.render().el); + view.delegateEvents(); + }); + }, + error: app.errorHandlerView.handleError({ + log: "An error occurred when saving a client" + }) + }); + + return false; + }, + + render: function() { + var data = { + client: this.model.toJSON(), + userInfo: getUserInfo(), + heartMode: heartMode + }; $(this.el).html(this.template(data)); - + this.listWidgetViews = []; - + var _self = this; - // build and bind registered redirect URI collection and view - _.each(this.model.get("redirect_uris"), function (redirectUri) { - _self.redirectUrisCollection.add(new URIModel({item:redirectUri})); - }); - - var redirectUriView = new ListWidgetView({ - type:'uri', - placeholder: 'https://', - helpBlockText: $.t('client.client-form.redirect-uris-help'), - collection: this.redirectUrisCollection}); - $("#redirectUris .controls",this.el).html(redirectUriView.render().el); - this.listWidgetViews.push(redirectUriView); - - // build and bind scopes - var scopes = this.model.get("scope"); - var scopeSet = scopes ? scopes.split(" ") : []; - _.each(scopeSet, function (scope) { - _self.scopeCollection.add(new Backbone.Model({item:scope})); - }); - - var scopeView = new ListWidgetView({ - placeholder: $.t('client.client-form.scope-placeholder'), - autocomplete: _.uniq(_.flatten(this.options.systemScopeList.unrestrictedScopes().pluck("value"))), - helpBlockText: $.t('client.client-form.scope-help'), - collection: this.scopeCollection}); - $("#scope .controls",this.el).html(scopeView.render().el); - this.listWidgetViews.push(scopeView); - - // build and bind contacts - _.each(this.model.get('contacts'), function (contact) { - _self.contactsCollection.add(new Backbone.Model({item:contact})); - }); - - var contactView = new ListWidgetView({ - placeholder: $.t('client.client-form.contacts-placeholder'), - helpBlockText: $.t('client.client-form.contacts-help'), - collection: this.contactsCollection}); - $("#contacts .controls div", this.el).html(contactView.render().el); - this.listWidgetViews.push(contactView); - - // build and bind post-logout redirect URIs - _.each(this.model.get('post_logout_redirect_uris'), function(postLogoutRedirectUri) { - _self.postLogoutRedirectUrisCollection.add(new URIModel({item:postLogoutRedirectUri})); - }); - - var postLogoutRedirectUrisView = new ListWidgetView({ - type: 'uri', - placeholder: 'https://', - helpBlockText: $.t('client.client-form.post-logout-help'), - collection: this.postLogoutRedirectUrisCollection}); - $('#postLogoutRedirectUris .controls', this.el).html(postLogoutRedirectUrisView.render().el); - this.listWidgetViews.push(postLogoutRedirectUrisView); - - // build and bind claims redirect URIs - _.each(this.model.get('claimsRedirectUris'), function(claimsRedirectUri) { - _self.claimsRedirectUrisCollection.add(new URIModel({item:claimsRedirectUri})); - }); - - var claimsRedirectUrisView = new ListWidgetView({ - type: 'uri', - placeholder: 'https://', - helpBlockText: $.t('client.client-form.claims-redirect-uris-help'), - collection: this.claimsRedirectUrisCollection}); - $('#claimsRedirectUris .controls', this.el).html(claimsRedirectUrisView.render().el); - this.listWidgetViews.push(claimsRedirectUrisView); - - // build and bind request URIs - _.each(this.model.get('request_uris'), function (requestUri) { - _self.requestUrisCollection.add(new URIModel({item:requestUri})); - }); - - var requestUriView = new ListWidgetView({ - type: 'uri', - placeholder: 'https://', - helpBlockText: $.t('client.client-form.request-uri-help'), - collection: this.requestUrisCollection}); - $('#requestUris .controls', this.el).html(requestUriView.render().el); - this.listWidgetViews.push(requestUriView); - - // build and bind default ACR values - _.each(this.model.get('default_acr_values'), function (defaultAcrValue) { - _self.defaultAcrValuesCollection.add(new Backbone.Model({item:defaultAcrValue})); - }); - - var defaultAcrView = new ListWidgetView({ - placeholder: $.t('client.client-form.acr-values-placeholder'), - // TODO: autocomplete from spec - helpBlockText: $.t('client.client-form.acr-values-help'), - collection: this.defaultAcrValuesCollection}); - $('#defaultAcrValues .controls', this.el).html(defaultAcrView.render().el); - this.listWidgetViews.push(defaultAcrView); - - this.toggleClientCredentials(); - this.previewLogo(); - this.toggleJWKSetType(); - - // disable unsupported JOSE algorithms - this.disableUnsupportedJOSEItems(app.serverConfiguration.request_object_signing_alg_values_supported, '#requestObjectSigningAlg option'); - this.disableUnsupportedJOSEItems(app.serverConfiguration.userinfo_signing_alg_values_supported, '#userInfoSignedResponseAlg option'); - this.disableUnsupportedJOSEItems(app.serverConfiguration.userinfo_encryption_alg_values_supported, '#userInfoEncryptedResponseAlg option'); - this.disableUnsupportedJOSEItems(app.serverConfiguration.userinfo_encryption_enc_values_supported, '#userInfoEncryptedResponseEnc option'); - this.disableUnsupportedJOSEItems(app.serverConfiguration.id_token_signing_alg_values_supported, '#idTokenSignedResponseAlg option'); - this.disableUnsupportedJOSEItems(app.serverConfiguration.id_token_encryption_alg_values_supported, '#idTokenEncryptedResponseAlg option'); - this.disableUnsupportedJOSEItems(app.serverConfiguration.id_token_encryption_enc_values_supported, '#idTokenEncryptedResponseEnc option'); - this.disableUnsupportedJOSEItems(app.serverConfiguration.token_endpoint_auth_signing_alg_values_supported, '#tokenEndpointAuthSigningAlg option'); - - this.$('.nyi').clickover({ - placement: 'right', - title: $.t('common.not-yet-implemented'), - content: $.t('common.not-yet-implemented-content') - }); - - - $(this.el).i18n(); - return this; + // build and bind registered redirect URI collection and view + _.each(this.model.get("redirect_uris"), function(redirectUri) { + _self.redirectUrisCollection.add(new URIModel({ + item: redirectUri + })); + }); + + var redirectUriView = new ListWidgetView({ + type: 'uri', + placeholder: 'https://', + helpBlockText: $.t('client.client-form.redirect-uris-help'), + collection: this.redirectUrisCollection + }); + $("#redirectUris .controls", this.el).html(redirectUriView.render().el); + this.listWidgetViews.push(redirectUriView); + + // build and bind scopes + var scopes = this.model.get("scope"); + var scopeSet = scopes ? scopes.split(" ") : []; + _.each(scopeSet, function(scope) { + _self.scopeCollection.add(new Backbone.Model({ + item: scope + })); + }); + + var scopeView = new ListWidgetView({ + placeholder: $.t('client.client-form.scope-placeholder'), + autocomplete: _.uniq(_.flatten(this.options.systemScopeList.unrestrictedScopes().pluck("value"))), + helpBlockText: $.t('client.client-form.scope-help'), + collection: this.scopeCollection + }); + $("#scope .controls", this.el).html(scopeView.render().el); + this.listWidgetViews.push(scopeView); + + // build and bind contacts + _.each(this.model.get('contacts'), function(contact) { + _self.contactsCollection.add(new Backbone.Model({ + item: contact + })); + }); + + var contactView = new ListWidgetView({ + placeholder: $.t('client.client-form.contacts-placeholder'), + helpBlockText: $.t('client.client-form.contacts-help'), + collection: this.contactsCollection + }); + $("#contacts .controls div", this.el).html(contactView.render().el); + this.listWidgetViews.push(contactView); + + // build and bind post-logout redirect URIs + _.each(this.model.get('post_logout_redirect_uris'), function(postLogoutRedirectUri) { + _self.postLogoutRedirectUrisCollection.add(new URIModel({ + item: postLogoutRedirectUri + })); + }); + + var postLogoutRedirectUrisView = new ListWidgetView({ + type: 'uri', + placeholder: 'https://', + helpBlockText: $.t('client.client-form.post-logout-help'), + collection: this.postLogoutRedirectUrisCollection + }); + $('#postLogoutRedirectUris .controls', this.el).html(postLogoutRedirectUrisView.render().el); + this.listWidgetViews.push(postLogoutRedirectUrisView); + + // build and bind claims redirect URIs + _.each(this.model.get('claimsRedirectUris'), function(claimsRedirectUri) { + _self.claimsRedirectUrisCollection.add(new URIModel({ + item: claimsRedirectUri + })); + }); + + var claimsRedirectUrisView = new ListWidgetView({ + type: 'uri', + placeholder: 'https://', + helpBlockText: $.t('client.client-form.claims-redirect-uris-help'), + collection: this.claimsRedirectUrisCollection + }); + $('#claimsRedirectUris .controls', this.el).html(claimsRedirectUrisView.render().el); + this.listWidgetViews.push(claimsRedirectUrisView); + + // build and bind request URIs + _.each(this.model.get('request_uris'), function(requestUri) { + _self.requestUrisCollection.add(new URIModel({ + item: requestUri + })); + }); + + var requestUriView = new ListWidgetView({ + type: 'uri', + placeholder: 'https://', + helpBlockText: $.t('client.client-form.request-uri-help'), + collection: this.requestUrisCollection + }); + $('#requestUris .controls', this.el).html(requestUriView.render().el); + this.listWidgetViews.push(requestUriView); + + // build and bind default ACR values + _.each(this.model.get('default_acr_values'), function(defaultAcrValue) { + _self.defaultAcrValuesCollection.add(new Backbone.Model({ + item: defaultAcrValue + })); + }); + + var defaultAcrView = new ListWidgetView({ + placeholder: $.t('client.client-form.acr-values-placeholder'), + // TODO: autocomplete from spec + helpBlockText: $.t('client.client-form.acr-values-help'), + collection: this.defaultAcrValuesCollection + }); + $('#defaultAcrValues .controls', this.el).html(defaultAcrView.render().el); + this.listWidgetViews.push(defaultAcrView); + + this.toggleClientCredentials(); + this.previewLogo(); + this.toggleJWKSetType(); + + // disable unsupported JOSE algorithms + this.disableUnsupportedJOSEItems(app.serverConfiguration.request_object_signing_alg_values_supported, '#requestObjectSigningAlg option'); + this.disableUnsupportedJOSEItems(app.serverConfiguration.userinfo_signing_alg_values_supported, '#userInfoSignedResponseAlg option'); + this.disableUnsupportedJOSEItems(app.serverConfiguration.userinfo_encryption_alg_values_supported, '#userInfoEncryptedResponseAlg option'); + this.disableUnsupportedJOSEItems(app.serverConfiguration.userinfo_encryption_enc_values_supported, '#userInfoEncryptedResponseEnc option'); + this.disableUnsupportedJOSEItems(app.serverConfiguration.id_token_signing_alg_values_supported, '#idTokenSignedResponseAlg option'); + this.disableUnsupportedJOSEItems(app.serverConfiguration.id_token_encryption_alg_values_supported, '#idTokenEncryptedResponseAlg option'); + this.disableUnsupportedJOSEItems(app.serverConfiguration.id_token_encryption_enc_values_supported, '#idTokenEncryptedResponseEnc option'); + this.disableUnsupportedJOSEItems(app.serverConfiguration.token_endpoint_auth_signing_alg_values_supported, '#tokenEndpointAuthSigningAlg option'); + + this.$('.nyi').clickover({ + placement: 'right', + title: $.t('common.not-yet-implemented'), + content: $.t('common.not-yet-implemented-content') + }); + + $(this.el).i18n(); + return this; } - + }); -ui.routes.push({path: "dev/dynreg", name: "dynReg", callback: - function() { - +ui.routes.push({ + path: "dev/dynreg", + name: "dynReg", + callback: function() { + this.breadCrumbView.collection.reset(); - this.breadCrumbView.collection.add([ - {text:$.t('admin.home'), href:""}, - {text:$.t('admin.self-service-client'), href:"manage/#dev/dynreg"} - ]); - - var view = new DynRegRootView({systemScopeList: this.systemScopeList}); - - this.updateSidebar('dev/dynreg'); - + this.breadCrumbView.collection.add([{ + text: $.t('admin.home'), + href: "" + }, { + text: $.t('admin.self-service-client'), + href: "manage/#dev/dynreg" + }]); + + var view = new DynRegRootView({ + systemScopeList: this.systemScopeList + }); + + this.updateSidebar('dev/dynreg'); + view.load(function() { - $('#content').html(view.render().el); - - setPageTitle($.t('admin.self-service-client')); + $('#content').html(view.render().el); + + setPageTitle($.t('admin.self-service-client')); }); - + } }); -ui.routes.push({path: "dev/dynreg/new", name: "newDynReg", callback: - function() { +ui.routes.push({ + path: "dev/dynreg/new", + name: "newDynReg", + callback: function() { this.breadCrumbView.collection.reset(); - this.breadCrumbView.collection.add([ - {text:$.t('admin.home'), href:""}, - {text:$.t('admin.self-service-client'), href:"manage/#dev/dynreg"}, - {text:$.t('dynreg.new-client'), href:"manage/#dev/dynreg/new"} - ]); - - this.updateSidebar('dev/dynreg'); - + this.breadCrumbView.collection.add([{ + text: $.t('admin.home'), + href: "" + }, { + text: $.t('admin.self-service-client'), + href: "manage/#dev/dynreg" + }, { + text: $.t('dynreg.new-client'), + href: "manage/#dev/dynreg/new" + }]); + + this.updateSidebar('dev/dynreg'); + var client = new DynRegClient(); - var view = new DynRegEditView({model: client, systemScopeList:this.systemScopeList}); - + var view = new DynRegEditView({ + model: client, + systemScopeList: this.systemScopeList + }); + view.load(function() { - + var userInfo = getUserInfo(); var contacts = []; if (userInfo != null && userInfo.email != null) { contacts.push(userInfo.email); } - + if (heartMode) { client.set({ - require_auth_time:true, - default_max_age:60000, + require_auth_time: true, + default_max_age: 60000, scope: _.uniq(_.flatten(app.systemScopeList.defaultUnrestrictedScopes().pluck("value"))).join(" "), token_endpoint_auth_method: 'private_key_jwt', grant_types: ["authorization_code"], response_types: ["code"], subject_type: "public", contacts: contacts - }, { silent: true }); + }, { + silent: true + }); } else { client.set({ - require_auth_time:true, - default_max_age:60000, + require_auth_time: true, + default_max_age: 60000, scope: _.uniq(_.flatten(app.systemScopeList.defaultUnrestrictedScopes().pluck("value"))).join(" "), token_endpoint_auth_method: 'client_secret_basic', grant_types: ["authorization_code"], response_types: ["code"], subject_type: "public", contacts: contacts - }, { silent: true }); + }, { + silent: true + }); } - + $('#content').html(view.render().el); view.delegateEvents(); setPageTitle($.t('dynreg.new-client')); - + }); - + } }); -ui.routes.push({path: "dev/dynreg/edit", name: "editDynReg", callback: - function() { +ui.routes.push({ + path: "dev/dynreg/edit", + name: "editDynReg", + callback: function() { this.breadCrumbView.collection.reset(); - this.breadCrumbView.collection.add([ - {text:$.t('admin.home'), href:""}, - {text:$.t('admin.self-service-client'), href:"manage/#dev/dynreg"}, - {text:$.t('dynreg.edit-existing'), href:"manage/#dev/dynreg/edit"} - ]); - - this.updateSidebar('dev/dynreg'); - + this.breadCrumbView.collection.add([{ + text: $.t('admin.home'), + href: "" + }, { + text: $.t('admin.self-service-client'), + href: "manage/#dev/dynreg" + }, { + text: $.t('dynreg.edit-existing'), + href: "manage/#dev/dynreg/edit" + }]); + + this.updateSidebar('dev/dynreg'); + setPageTitle($.t('dynreg.edit-existing')); - // note that this doesn't actually load the client, that's supposed to happen elsewhere... + // note that this doesn't actually load the client, that's supposed to + // happen elsewhere... } }); diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/grant.js b/openid-connect-server-webapp/src/main/webapp/resources/js/grant.js index 948e1c17aa..c547b1efd0 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/grant.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/grant.js @@ -16,84 +16,95 @@ *******************************************************************************/ var ApprovedSiteModel = Backbone.Model.extend({ idAttribute: 'id', - - initialize: function() { }, - + + initialize: function() { + }, + urlRoot: 'api/approved' - + }); var ApprovedSiteCollection = Backbone.Collection.extend({ - initialize: function() { }, + initialize: function() { + }, model: ApprovedSiteModel, url: 'api/approved' }); - var ApprovedSiteListView = Backbone.View.extend({ tagName: 'span', - - initialize:function(options) { + + initialize: function(options) { this.options = options; }, - load:function(callback) { - if (this.model.isFetched && - this.options.clientList.isFetched && - this.options.systemScopeList.isFetched) { - callback(); - return; - } - - $('#loadingbox').sheet('show'); - $('#loading').html( - '' + $.t('grant.grant-table.approved-sites') + ' ' + - '' + $.t('common.clients') + ' ' + - '' + $.t('common.scopes') + ' ' - ); - - $.when(this.model.fetchIfNeeded({success:function(e) {$('#loading-grants').addClass('label-success');}, error:app.errorHandlerView.handleError()}), - this.options.clientList.fetchIfNeeded({success:function(e) {$('#loading-clients').addClass('label-success');}, error:app.errorHandlerView.handleError()}), - this.options.systemScopeList.fetchIfNeeded({success:function(e) {$('#loading-scopes').addClass('label-success');}, error:app.errorHandlerView.handleError()})) - .done(function() { - $('#loadingbox').sheet('hide'); - callback(); - }); - }, - + load: function(callback) { + if (this.model.isFetched && this.options.clientList.isFetched && this.options.systemScopeList.isFetched) { + callback(); + return; + } + + $('#loadingbox').sheet('show'); + $('#loading').html('' + $.t('grant.grant-table.approved-sites') + ' ' + '' + $.t('common.clients') + ' ' + '' + $.t('common.scopes') + ' '); + + $.when(this.model.fetchIfNeeded({ + success: function(e) { + $('#loading-grants').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + }), this.options.clientList.fetchIfNeeded({ + success: function(e) { + $('#loading-clients').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + }), this.options.systemScopeList.fetchIfNeeded({ + success: function(e) { + $('#loading-scopes').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + })).done(function() { + $('#loadingbox').sheet('hide'); + callback(); + }); + }, + events: { - "click .refresh-table":"refreshTable" + "click .refresh-table": "refreshTable" }, - - render:function (eventName) { + + render: function(eventName) { $(this.el).html($('#tmpl-grant-table').html()); - + var approvedSiteCount = 0; - + var _self = this; - + _.each(this.model.models, function(approvedSite) { // look up client var client = this.options.clientList.getByClientId(approvedSite.get('clientId')); - + if (client != null) { - - var view = new ApprovedSiteView({model: approvedSite, client: client, systemScopeList: this.options.systemScopeList}); + + var view = new ApprovedSiteView({ + model: approvedSite, + client: client, + systemScopeList: this.options.systemScopeList + }); view.parentView = _self; $('#grant-table', this.el).append(view.render().el); approvedSiteCount = approvedSiteCount + 1; - + } - + }, this); - + this.togglePlaceholder(); $(this.el).i18n(); return this; }, - - togglePlaceholder:function() { + + togglePlaceholder: function() { // count entries if (this.model.length > 0) { $('#grant-table', this.el).show(); @@ -102,54 +113,62 @@ var ApprovedSiteListView = Backbone.View.extend({ $('#grant-table', this.el).hide(); $('#grant-table-empty', this.el).show(); } - + }, - - refreshTable:function(e) { - e.preventDefault(); - var _self = this; - $('#loadingbox').sheet('show'); - $('#loading').html( - '' + $.t('grant.grant-table.approved-sites') + ' ' + - '' + $.t('common.clients') + ' ' + - '' + $.t('common.scopes') + ' ' - ); - - $.when(this.model.fetch({success:function(e) {$('#loading-grants').addClass('label-success');}, error:app.errorHandlerView.handleError()}), - this.options.clientList.fetch({success:function(e) {$('#loading-clients').addClass('label-success');}, error:app.errorHandlerView.handleError()}), - this.options.systemScopeList.fetch({success:function(e) {$('#loading-scopes').addClass('label-success');}, error:app.errorHandlerView.handleError()})) - .done(function() { - $('#loadingbox').sheet('hide'); - _self.render(); - }); - } + + refreshTable: function(e) { + e.preventDefault(); + var _self = this; + $('#loadingbox').sheet('show'); + $('#loading').html('' + $.t('grant.grant-table.approved-sites') + ' ' + '' + $.t('common.clients') + ' ' + '' + $.t('common.scopes') + ' '); + + $.when(this.model.fetch({ + success: function(e) { + $('#loading-grants').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + }), this.options.clientList.fetch({ + success: function(e) { + $('#loading-clients').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + }), this.options.systemScopeList.fetch({ + success: function(e) { + $('#loading-scopes').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + })).done(function() { + $('#loadingbox').sheet('hide'); + _self.render(); + }); + } }); var ApprovedSiteView = Backbone.View.extend({ tagName: 'tr', - + initialize: function(options) { - this.options = options; + this.options = options; if (!this.template) { this.template = _.template($('#tmpl-grant').html()); } - if (!this.scopeTemplate) { - this.scopeTemplate = _.template($('#tmpl-scope-list').html()); - } + if (!this.scopeTemplate) { + this.scopeTemplate = _.template($('#tmpl-scope-list').html()); + } - if (!this.moreInfoTemplate) { - this.moreInfoTemplate = _.template($('#tmpl-client-more-info-block').html()); - } + if (!this.moreInfoTemplate) { + this.moreInfoTemplate = _.template($('#tmpl-client-more-info-block').html()); + } }, - render: function() { - + render: function() { + var creationDate = this.model.get("creationDate"); var accessDate = this.model.get("accessDate"); var timeoutDate = this.model.get("timeoutDate"); - + var displayCreationDate = $.t('grant.grant-table.unknown'); var hoverCreationDate = ""; if ((creationDate != null) && moment(creationDate).isValid()) { @@ -178,7 +197,7 @@ var ApprovedSiteView = Backbone.View.extend({ var hoverTimeoutDate = ""; if (timeoutDate == null) { displayTimeoutDate = $.t('grant.grant-table.never'); - } else if(moment(timeoutDate).isValid()) { + } else if (moment(timeoutDate).isValid()) { timeoutDate = moment(timeoutDate); if (moment().diff(timeoutDate, 'months') < 6) { displayTimeoutDate = timeoutDate.fromNow(); @@ -188,62 +207,80 @@ var ApprovedSiteView = Backbone.View.extend({ hoverTimeoutDate = timeoutDate.format("LLL"); } - - var formattedDate = {displayCreationDate: displayCreationDate, hoverCreationDate: hoverCreationDate, - displayAccessDate: displayAccessDate, hoverAccessDate: hoverAccessDate, - displayTimeoutDate: displayTimeoutDate, hoverTimeoutDate: hoverTimeoutDate}; - - var json = {grant: this.model.toJSON(), client: this.options.client.toJSON(), formattedDate: formattedDate}; - + var formattedDate = { + displayCreationDate: displayCreationDate, + hoverCreationDate: hoverCreationDate, + displayAccessDate: displayAccessDate, + hoverAccessDate: hoverAccessDate, + displayTimeoutDate: displayTimeoutDate, + hoverTimeoutDate: hoverTimeoutDate + }; + + var json = { + grant: this.model.toJSON(), + client: this.options.client.toJSON(), + formattedDate: formattedDate + }; + this.$el.html(this.template(json)); - $('.scope-list', this.el).html(this.scopeTemplate({scopes: this.model.get('allowedScopes'), systemScopes: this.options.systemScopeList})); - - $('.client-more-info-block', this.el).html(this.moreInfoTemplate({client: this.options.client.toJSON()})); - - this.$('.dynamically-registered').tooltip({title: $.t('grant.grant-table.dynamically-registered')}); - this.$('.tokens').tooltip({title: $.t('grant.grant-table.active-tokens')}); - $(this.el).i18n(); + $('.scope-list', this.el).html(this.scopeTemplate({ + scopes: this.model.get('allowedScopes'), + systemScopes: this.options.systemScopeList + })); + + $('.client-more-info-block', this.el).html(this.moreInfoTemplate({ + client: this.options.client.toJSON() + })); + + this.$('.dynamically-registered').tooltip({ + title: $.t('grant.grant-table.dynamically-registered') + }); + this.$('.tokens').tooltip({ + title: $.t('grant.grant-table.active-tokens') + }); + $(this.el).i18n(); return this; }, - + events: { 'click .btn-delete': 'deleteApprovedSite', 'click .toggleMoreInformation': 'toggleMoreInformation' }, - - deleteApprovedSite:function(e) { - e.preventDefault(); + + deleteApprovedSite: function(e) { + e.preventDefault(); if (confirm("Are you sure you want to revoke access to this site?")) { var self = this; - - this.model.destroy({ - dataType: false, processData: false, - success:function () { - self.$el.fadeTo("fast", 0.00, function () { //fade - $(this).slideUp("fast", function () { //slide up - $(this).remove(); //then remove from the DOM - self.parentView.togglePlaceholder(); - }); - }); - }, - error:app.errorHandlerView.handleError() - }); - - this.parentView.delegateEvents(); + + this.model.destroy({ + dataType: false, + processData: false, + success: function() { + self.$el.fadeTo("fast", 0.00, function() { // fade + $(this).slideUp("fast", function() { // slide up + $(this).remove(); // then remove from the DOM + self.parentView.togglePlaceholder(); + }); + }); + }, + error: app.errorHandlerView.handleError() + }); + + this.parentView.delegateEvents(); } - + return false; }, - - toggleMoreInformation:function(e) { + + toggleMoreInformation: function(e) { e.preventDefault(); if ($('.moreInformation', this.el).is(':visible')) { // hide it $('.moreInformation', this.el).hide('fast'); $('.toggleMoreInformation i', this.el).attr('class', 'icon-chevron-right'); $('.moreInformationContainer', this.el).removeClass('alert').removeClass('alert-info').addClass('muted'); - + } else { // show it $('.moreInformation', this.el).show('fast'); @@ -251,36 +288,44 @@ var ApprovedSiteView = Backbone.View.extend({ $('.moreInformationContainer', this.el).addClass('alert').addClass('alert-info').removeClass('muted'); } }, - - close:function() { + + close: function() { $(this.el).unbind(); $(this.el).empty(); } }); -ui.routes.push({path: "user/approved", name: "approvedSites", callback: - +ui.routes.push({ + path: "user/approved", + name: "approvedSites", + callback: + function() { this.breadCrumbView.collection.reset(); - this.breadCrumbView.collection.add([ - {text:$.t('admin.home'), href:""}, - {text:$.t('grant.manage-approved-sites'), href:"manage/#user/approve"} - ]); - - this.updateSidebar('user/approved'); - - var view = new ApprovedSiteListView({model:this.approvedSiteList, clientList: this.clientList, systemScopeList: this.systemScopeList}); - view.load( - function(collection, response, options) { - $('#content').html(view.render().el); - setPageTitle($.t('grant.manage-approved-sites')); - } - ); + this.breadCrumbView.collection.add([{ + text: $.t('admin.home'), + href: "" + }, { + text: $.t('grant.manage-approved-sites'), + href: "manage/#user/approve" + }]); + + this.updateSidebar('user/approved'); + + var view = new ApprovedSiteListView({ + model: this.approvedSiteList, + clientList: this.clientList, + systemScopeList: this.systemScopeList + }); + view.load(function(collection, response, options) { + $('#content').html(view.render().el); + setPageTitle($.t('grant.manage-approved-sites')); + }); } }); ui.templates.push('resources/template/grant.html'); ui.init.push(function(app) { - app.approvedSiteList = new ApprovedSiteCollection(); + app.approvedSiteList = new ApprovedSiteCollection(); }); diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/profile.js b/openid-connect-server-webapp/src/main/webapp/resources/js/profile.js index e9fd39ffe2..87b402d142 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/profile.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/profile.js @@ -14,21 +14,28 @@ * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ -ui.routes.push({path: "user/profile", name: "profile", callback: - function() { +ui.routes.push({ + path: "user/profile", + name: "profile", + callback: function() { - this.breadCrumbView.collection.reset(); - this.breadCrumbView.collection.add([ - {text:$.t('admin.home'), href:""}, - {text:$.t('admin.user-profile.show'), href:"manage/#user/profile"} - ]); - - this.updateSidebar('user/profile'); - - var view = new UserProfileView({model: getUserInfo()}); - $('#content').html(view.render().el); - - setPageTitle($.t('admin.user-profile.show')); - - } + this.breadCrumbView.collection.reset(); + this.breadCrumbView.collection.add([{ + text: $.t('admin.home'), + href: "" + }, { + text: $.t('admin.user-profile.show'), + href: "manage/#user/profile" + }]); + + this.updateSidebar('user/profile'); + + var view = new UserProfileView({ + model: getUserInfo() + }); + $('#content').html(view.render().el); + + setPageTitle($.t('admin.user-profile.show')); + + } }); \ No newline at end of file diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/rsreg.js b/openid-connect-server-webapp/src/main/webapp/resources/js/rsreg.js index 3507c65acc..8713c583e7 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/rsreg.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/rsreg.js @@ -15,492 +15,565 @@ * limitations under the License. *******************************************************************************/ var ResRegClient = Backbone.Model.extend({ - idAttribute: "client_id", - - defaults:{ - client_id:null, - client_secret:null, - client_name:null, - client_uri:null, - logo_uri:null, - contacts:[], - tos_uri:null, - token_endpoint_auth_method:null, - scope:null, - policy_uri:null, - - jwks_uri:null, - jwks:null, - jwksType:'URI', - - application_type:null, - registration_access_token:null, - registration_client_uri:null - }, - - sync: function(method, model, options){ - if (model.get('registration_access_token')) { - var headers = options.headers ? options.headers : {}; - headers['Authorization'] = 'Bearer ' + model.get('registration_access_token'); - options.headers = headers; - } - - return this.constructor.__super__.sync(method, model, options); - }, - - urlRoot:'resource' - + idAttribute: "client_id", + + defaults: { + client_id: null, + client_secret: null, + client_name: null, + client_uri: null, + logo_uri: null, + contacts: [], + tos_uri: null, + token_endpoint_auth_method: null, + scope: null, + policy_uri: null, + + jwks_uri: null, + jwks: null, + jwksType: 'URI', + + application_type: null, + registration_access_token: null, + registration_client_uri: null + }, + + sync: function(method, model, options) { + if (model.get('registration_access_token')) { + var headers = options.headers ? options.headers : {}; + headers['Authorization'] = 'Bearer ' + model.get('registration_access_token'); + options.headers = headers; + } + + return this.constructor.__super__.sync(method, model, options); + }, + + urlRoot: 'resource' + }); var ResRegRootView = Backbone.View.extend({ - + tagName: 'span', - - initialize:function(options) { - this.options = options; - + + initialize: function(options) { + this.options = options; + }, - - events:{ - "click #newreg":"newReg", - "click #editreg":"editReg" + + events: { + "click #newreg": "newReg", + "click #editreg": "editReg" }, - - load:function(callback) { - if (this.options.systemScopeList.isFetched) { - callback(); - return; - } - - $('#loadingbox').sheet('show'); - $('#loading').html('' + $.t('common.scopes') + ' '); - - $.when(this.options.systemScopeList.fetchIfNeeded({success:function(e) {$('#loading-scopes').addClass('label-success');}, error:app.errorHandlerView.handleError()})) - .done(function() { - $('#loadingbox').sheet('hide'); - callback(); - }); + + load: function(callback) { + if (this.options.systemScopeList.isFetched) { + callback(); + return; + } + + $('#loadingbox').sheet('show'); + $('#loading').html('' + $.t('common.scopes') + ' '); + + $.when(this.options.systemScopeList.fetchIfNeeded({ + success: function(e) { + $('#loading-scopes').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + })).done(function() { + $('#loadingbox').sheet('hide'); + callback(); + }); }, - - render:function() { - $(this.el).html($('#tmpl-rsreg').html()); - $(this.el).i18n(); - return this; + + render: function() { + $(this.el).html($('#tmpl-rsreg').html()); + $(this.el).i18n(); + return this; }, - - newReg:function(e) { - e.preventDefault(); - this.remove(); - app.navigate('dev/resource/new', {trigger: true}); + + newReg: function(e) { + e.preventDefault(); + this.remove(); + app.navigate('dev/resource/new', { + trigger: true + }); }, - - editReg:function(e) { - e.preventDefault(); + + editReg: function(e) { + e.preventDefault(); var clientId = $('#clientId').val(); var token = $('#regtoken').val(); - + var client = new ResRegClient({ client_id: clientId, registration_access_token: token }); - + var self = this; - + client.fetch({ success: function() { - - if (client.get("jwks")) { - client.set({ - jwksType: "VAL" - }, { silent: true }); - } else { - client.set({ - jwksType: "URI" - }, { silent: true }); - } - - var view = new ResRegEditView({model: client, systemScopeList: app.systemScopeList}); - - view.load(function() { - $('#content').html(view.render().el); - view.delegateEvents(); - setPageTitle($.t('rsreg.new')); - app.navigate('dev/resource/edit', {trigger: true}); - self.remove(); - }); - }, - error:app.errorHandlerView.handleError({message: $.t('dynreg.invalid-access-token')}) + + if (client.get("jwks")) { + client.set({ + jwksType: "VAL" + }, { + silent: true + }); + } else { + client.set({ + jwksType: "URI" + }, { + silent: true + }); + } + + var view = new ResRegEditView({ + model: client, + systemScopeList: app.systemScopeList + }); + + view.load(function() { + $('#content').html(view.render().el); + view.delegateEvents(); + setPageTitle($.t('rsreg.new')); + app.navigate('dev/resource/edit', { + trigger: true + }); + self.remove(); + }); + }, + error: app.errorHandlerView.handleError({ + message: $.t('dynreg.invalid-access-token') + }) }); } - + }); var ResRegEditView = Backbone.View.extend({ - + tagName: 'span', - - initialize:function(options) { - this.options = options; - if (!this.template) { - this.template = _.template($('#tmpl-rsreg-resource-form').html()); - } - - this.redirectUrisCollection = new Backbone.Collection(); - this.scopeCollection = new Backbone.Collection(); - this.contactsCollection = new Backbone.Collection(); - this.defaultAcrValuesCollection = new Backbone.Collection(); - this.requestUrisCollection = new Backbone.Collection(); - - this.listWidgetViews = []; + + initialize: function(options) { + this.options = options; + if (!this.template) { + this.template = _.template($('#tmpl-rsreg-resource-form').html()); + } + + this.redirectUrisCollection = new Backbone.Collection(); + this.scopeCollection = new Backbone.Collection(); + this.contactsCollection = new Backbone.Collection(); + this.defaultAcrValuesCollection = new Backbone.Collection(); + this.requestUrisCollection = new Backbone.Collection(); + + this.listWidgetViews = []; + }, + + load: function(callback) { + if (this.options.systemScopeList.isFetched) { + callback(); + return; + } + + $('#loadingbox').sheet('show'); + $('#loading').html('' + $.t('common.scopes') + ' '); + + $.when(this.options.systemScopeList.fetchIfNeeded({ + success: function(e) { + $('#loading-scopes').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + })).done(function() { + $('#loadingbox').sheet('hide'); + callback(); + }); + }, + + events: { + "click .btn-save": "saveClient", + "click .btn-cancel": "cancel", + "click .btn-delete": "deleteClient", + "change #logoUri input": "previewLogo", + "change #tokenEndpointAuthMethod input:radio": "toggleClientCredentials", + "change #jwkSelector input:radio": "toggleJWKSetType" + }, + + cancel: function(e) { + e.preventDefault(); + app.navigate('dev/resource', { + trigger: true + }); + }, + + deleteClient: function(e) { + e.preventDefault(); + + if (confirm($.t('client.client-table.confirm'))) { + var self = this; + + this.model.destroy({ + dataType: false, + processData: false, + success: function() { + self.remove(); + app.navigate('dev/resource', { + trigger: true + }); + }, + error: app.errorHandlerView.handleError() + }); + + } + + return false; + }, + + previewLogo: function() { + if ($('#logoUri input', this.el).val()) { + $('#logoPreview', this.el).empty(); + $('#logoPreview', this.el).attr('src', $('#logoUri input', this.el).val()); + } else { + // $('#logoBlock', this.el).hide(); + $('#logoPreview', this.el).attr('src', 'resources/images/logo_placeholder.gif'); + } + }, + + /** + * Set up the form based on the current state of the tokenEndpointAuthMethod + * parameter + * + * @param event + */ + toggleClientCredentials: function() { + + var tokenEndpointAuthMethod = $('#tokenEndpointAuthMethod input', this.el).filter(':checked').val(); + + // show or hide the signing algorithm method depending on what's + // selected + if (tokenEndpointAuthMethod == 'private_key_jwt' || tokenEndpointAuthMethod == 'client_secret_jwt') { + $('#tokenEndpointAuthSigningAlg', this.el).show(); + } else { + $('#tokenEndpointAuthSigningAlg', this.el).hide(); + } + }, + + /** + * Set up the form based on the JWK Set selector + */ + toggleJWKSetType: function() { + var jwkSelector = $('#jwkSelector input:radio', this.el).filter(':checked').val(); + + if (jwkSelector == 'URI') { + $('#jwksUri', this.el).show(); + $('#jwks', this.el).hide(); + } else if (jwkSelector == 'VAL') { + $('#jwksUri', this.el).hide(); + $('#jwks', this.el).show(); + } else { + $('#jwksUri', this.el).hide(); + $('#jwks', this.el).hide(); + } + + }, + + disableUnsupportedJOSEItems: function(serverSupported, query) { + var supported = ['default']; + if (serverSupported) { + supported = _.union(supported, serverSupported); + } + $(query, this.$el).each(function(idx) { + if (_.contains(supported, $(this).val())) { + $(this).prop('disabled', false); + } else { + $(this).prop('disabled', true); + } + }); + }, - - load:function(callback) { - if (this.options.systemScopeList.isFetched) { - callback(); - return; - } - - $('#loadingbox').sheet('show'); - $('#loading').html('' + $.t('common.scopes') + ' '); - - $.when(this.options.systemScopeList.fetchIfNeeded({success:function(e) {$('#loading-scopes').addClass('label-success');}, error:app.errorHandlerView.handleError()})) - .done(function() { - $('#loadingbox').sheet('hide'); - callback(); - }); + + // returns "null" if given the value "default" as a string, + // otherwise returns input value. useful for parsing the JOSE + // algorithm dropdowns + defaultToNull: function(value) { + if (value == 'default') { + return null; + } else { + return value; + } }, - - events:{ - "click .btn-save":"saveClient", - "click .btn-cancel":"cancel", - "click .btn-delete":"deleteClient", - "change #logoUri input":"previewLogo", - "change #tokenEndpointAuthMethod input:radio":"toggleClientCredentials", - "change #jwkSelector input:radio":"toggleJWKSetType" - }, - - cancel:function(e) { - e.preventDefault(); - app.navigate('dev/resource', {trigger: true}); - }, - - deleteClient:function (e) { - e.preventDefault(); - - if (confirm($.t('client.client-table.confirm'))) { - var self = this; - - this.model.destroy({ - dataType: false, processData: false, - success:function () { - self.remove(); - app.navigate('dev/resource', {trigger: true}); - }, - error:app.errorHandlerView.handleError() - }); - - } - - return false; - }, - - previewLogo:function() { - if ($('#logoUri input', this.el).val()) { - $('#logoPreview', this.el).empty(); - $('#logoPreview', this.el).attr('src', $('#logoUri input', this.el).val()); - } else { - //$('#logoBlock', this.el).hide(); - $('#logoPreview', this.el).attr('src', 'resources/images/logo_placeholder.gif'); - } - }, - - /** - * Set up the form based on the current state of the tokenEndpointAuthMethod parameter - * @param event - */ - toggleClientCredentials:function() { - - var tokenEndpointAuthMethod = $('#tokenEndpointAuthMethod input', this.el).filter(':checked').val(); - - // show or hide the signing algorithm method depending on what's selected - if (tokenEndpointAuthMethod == 'private_key_jwt' - || tokenEndpointAuthMethod == 'client_secret_jwt') { - $('#tokenEndpointAuthSigningAlg', this.el).show(); - } else { - $('#tokenEndpointAuthSigningAlg', this.el).hide(); - } - }, - - /** - * Set up the form based on the JWK Set selector - */ - toggleJWKSetType:function() { - var jwkSelector = $('#jwkSelector input:radio', this.el).filter(':checked').val(); - - if (jwkSelector == 'URI') { - $('#jwksUri', this.el).show(); - $('#jwks', this.el).hide(); - } else if (jwkSelector == 'VAL') { - $('#jwksUri', this.el).hide(); - $('#jwks', this.el).show(); - } else { - $('#jwksUri', this.el).hide(); - $('#jwks', this.el).hide(); - } - - }, - - disableUnsupportedJOSEItems:function(serverSupported, query) { - var supported = ['default']; - if (serverSupported) { - supported = _.union(supported, serverSupported); - } - $(query, this.$el).each(function(idx) { - if(_.contains(supported, $(this).val())) { - $(this).prop('disabled', false); - } else { - $(this).prop('disabled', true); - } - }); - - }, - - // returns "null" if given the value "default" as a string, otherwise returns input value. useful for parsing the JOSE algorithm dropdowns - defaultToNull:function(value) { - if (value == 'default') { - return null; - } else { - return value; - } - }, - - saveClient:function (e) { - e.preventDefault(); - - $('.control-group').removeClass('error'); - - // sync any leftover collection items - _.each(this.listWidgetViews, function(v) { - v.addItem($.Event('click')); - }); - - // build the scope object - var scopes = this.scopeCollection.pluck("item").join(" "); - - var contacts = this.contactsCollection.pluck('item'); - var userInfo = getUserInfo(); - if (userInfo && userInfo.email) { - if (!_.contains(contacts, userInfo.email)) { - contacts.push(userInfo.email); - } - } - - // process the JWKS - var jwksUri = null; - var jwks = null; - var jwkSelector = $('#jwkSelector input:radio', this.el).filter(':checked').val(); - - if (jwkSelector == 'URI') { - jwksUri = $('#jwksUri input').val(); - jwks = null; - } else if (jwkSelector == 'VAL') { - jwksUri = null; - try { - jwks = JSON.parse($('#jwks textarea').val()); - } catch (e) { - console.log("An error occurred when parsing the JWK Set"); - - //Display an alert with an error message - app.errorHandlerView.showErrorMessage($.t("client.client-form.error.jwk-set"), $.t("client.client-form.error.jwk-set-parse")); - return false; - } - } else { - jwksUri = null; - jwks = null; - } - - var attrs = { - client_name:$('#clientName input').val(), - logo_uri:$('#logoUri input').val(), - scope: scopes, - client_secret: null, // never send a client secret - tos_uri: $('#tosUri input').val(), - policy_uri: $('#policyUri input').val(), - client_uri: $('#clientUri input').val(), - application_type: $('#applicationType input').filter(':checked').val(), - jwks_uri: jwksUri, - jwks: jwks, - token_endpoint_auth_method: $('#tokenEndpointAuthMethod input').filter(':checked').val(), - contacts: contacts, - token_endpoint_auth_signing_alg: this.defaultToNull($('#tokenEndpointAuthSigningAlg select').val()) - }; - - // set all empty strings to nulls - for (var key in attrs) { - if (attrs[key] === "") { - attrs[key] = null; - } - } - - var _self = this; - this.model.save(attrs, { - success:function () { - // switch to an "edit" view - app.navigate('dev/resource/edit', {trigger: true}); - _self.remove(); - - if (_self.model.get("jwks")) { - _self.model.set({ - jwksType: "VAL" - }, { silent: true }); - } else { - _self.model.set({ - jwksType: "URI" - }, { silent: true }); - } - - var view = new ResRegEditView({model: _self.model, systemScopeList: _self.options.systemScopeList}); - - view.load(function() { - // reload - $('#content').html(view.render().el); - view.delegateEvents(); - }); - }, - error:app.errorHandlerView.handleError() - }); - - return false; - }, - - render:function() { - $(this.el).html(this.template({client: this.model.toJSON(), userInfo: getUserInfo()})); - + + saveClient: function(e) { + e.preventDefault(); + + $('.control-group').removeClass('error'); + + // sync any leftover collection items + _.each(this.listWidgetViews, function(v) { + v.addItem($.Event('click')); + }); + + // build the scope object + var scopes = this.scopeCollection.pluck("item").join(" "); + + var contacts = this.contactsCollection.pluck('item'); + var userInfo = getUserInfo(); + if (userInfo && userInfo.email) { + if (!_.contains(contacts, userInfo.email)) { + contacts.push(userInfo.email); + } + } + + // process the JWKS + var jwksUri = null; + var jwks = null; + var jwkSelector = $('#jwkSelector input:radio', this.el).filter(':checked').val(); + + if (jwkSelector == 'URI') { + jwksUri = $('#jwksUri input').val(); + jwks = null; + } else if (jwkSelector == 'VAL') { + jwksUri = null; + try { + jwks = JSON.parse($('#jwks textarea').val()); + } catch (e) { + console.log("An error occurred when parsing the JWK Set"); + + // Display an alert with an error message + app.errorHandlerView.showErrorMessage($.t("client.client-form.error.jwk-set"), $.t("client.client-form.error.jwk-set-parse")); + return false; + } + } else { + jwksUri = null; + jwks = null; + } + + var attrs = { + client_name: $('#clientName input').val(), + logo_uri: $('#logoUri input').val(), + scope: scopes, + client_secret: null, // never send a client secret + tos_uri: $('#tosUri input').val(), + policy_uri: $('#policyUri input').val(), + client_uri: $('#clientUri input').val(), + application_type: $('#applicationType input').filter(':checked').val(), + jwks_uri: jwksUri, + jwks: jwks, + token_endpoint_auth_method: $('#tokenEndpointAuthMethod input').filter(':checked').val(), + contacts: contacts, + token_endpoint_auth_signing_alg: this.defaultToNull($('#tokenEndpointAuthSigningAlg select').val()) + }; + + // set all empty strings to nulls + for ( var key in attrs) { + if (attrs[key] === "") { + attrs[key] = null; + } + } + + var _self = this; + this.model.save(attrs, { + success: function() { + // switch to an "edit" view + app.navigate('dev/resource/edit', { + trigger: true + }); + _self.remove(); + + if (_self.model.get("jwks")) { + _self.model.set({ + jwksType: "VAL" + }, { + silent: true + }); + } else { + _self.model.set({ + jwksType: "URI" + }, { + silent: true + }); + } + + var view = new ResRegEditView({ + model: _self.model, + systemScopeList: _self.options.systemScopeList + }); + + view.load(function() { + // reload + $('#content').html(view.render().el); + view.delegateEvents(); + }); + }, + error: app.errorHandlerView.handleError() + }); + + return false; + }, + + render: function() { + $(this.el).html(this.template({ + client: this.model.toJSON(), + userInfo: getUserInfo() + })); + this.listWidgetViews = []; - + var _self = this; - // build and bind scopes - var scopes = this.model.get("scope"); - var scopeSet = scopes ? scopes.split(" ") : []; - _.each(scopeSet, function (scope) { - _self.scopeCollection.add(new Backbone.Model({item:scope})); - }); - - var scopeView = new ListWidgetView({ - placeholder: $.t('client.client-form.scope-placeholder'), - autocomplete: _.uniq(_.flatten(this.options.systemScopeList.unrestrictedScopes().pluck("value"))), - helpBlockText: $.t('rsreg.client-form.scope-help'), - collection: this.scopeCollection}); - $("#scope .controls",this.el).html(scopeView.render().el); - this.listWidgetViews.push(scopeView); - - // build and bind contacts - _.each(this.model.get('contacts'), function (contact) { - _self.contactsCollection.add(new Backbone.Model({item:contact})); - }); - - var contactView = new ListWidgetView({ - placeholder: $.t('client.client-form.contacts-placeholder'), - helpBlockText: $.t('client.client-form.contacts-help'), - collection: this.contactsCollection}); - $("#contacts .controls", this.el).html(contactView.render().el); - this.listWidgetViews.push(contactView); - - - this.toggleClientCredentials(); - this.previewLogo(); - this.toggleJWKSetType(); - - // disable unsupported JOSE algorithms - this.disableUnsupportedJOSEItems(app.serverConfiguration.token_endpoint_auth_signing_alg_values_supported, '#tokenEndpointAuthSigningAlg option'); - - this.$('.nyi').clickover({ - placement: 'right', - title: $.t('common.not-yet-implemented'), - content: $.t('common.not-yet-implemented-content') - }); - - - $(this.el).i18n(); - return this; + // build and bind scopes + var scopes = this.model.get("scope"); + var scopeSet = scopes ? scopes.split(" ") : []; + _.each(scopeSet, function(scope) { + _self.scopeCollection.add(new Backbone.Model({ + item: scope + })); + }); + + var scopeView = new ListWidgetView({ + placeholder: $.t('client.client-form.scope-placeholder'), + autocomplete: _.uniq(_.flatten(this.options.systemScopeList.unrestrictedScopes().pluck("value"))), + helpBlockText: $.t('rsreg.client-form.scope-help'), + collection: this.scopeCollection + }); + $("#scope .controls", this.el).html(scopeView.render().el); + this.listWidgetViews.push(scopeView); + + // build and bind contacts + _.each(this.model.get('contacts'), function(contact) { + _self.contactsCollection.add(new Backbone.Model({ + item: contact + })); + }); + + var contactView = new ListWidgetView({ + placeholder: $.t('client.client-form.contacts-placeholder'), + helpBlockText: $.t('client.client-form.contacts-help'), + collection: this.contactsCollection + }); + $("#contacts .controls", this.el).html(contactView.render().el); + this.listWidgetViews.push(contactView); + + this.toggleClientCredentials(); + this.previewLogo(); + this.toggleJWKSetType(); + + // disable unsupported JOSE algorithms + this.disableUnsupportedJOSEItems(app.serverConfiguration.token_endpoint_auth_signing_alg_values_supported, '#tokenEndpointAuthSigningAlg option'); + + this.$('.nyi').clickover({ + placement: 'right', + title: $.t('common.not-yet-implemented'), + content: $.t('common.not-yet-implemented-content') + }); + + $(this.el).i18n(); + return this; } - + }); -ui.routes.push({path: "dev/resource", name: "resReg", callback: - function() { +ui.routes.push({ + path: "dev/resource", + name: "resReg", + callback: function() { this.breadCrumbView.collection.reset(); - this.breadCrumbView.collection.add([ - {text:$.t('admin.home'), href:""}, - {text:$.t('admin.self-service-resource'), href:"manage/#dev/resource"} - ]); - - this.updateSidebar('dev/resource'); - - var view = new ResRegRootView({systemScopeList: this.systemScopeList}); + this.breadCrumbView.collection.add([{ + text: $.t('admin.home'), + href: "" + }, { + text: $.t('admin.self-service-resource'), + href: "manage/#dev/resource" + }]); + + this.updateSidebar('dev/resource'); + + var view = new ResRegRootView({ + systemScopeList: this.systemScopeList + }); view.load(function() { - $('#content').html(view.render().el); - - setPageTitle($.t('admin.self-service-resource')); + $('#content').html(view.render().el); + + setPageTitle($.t('admin.self-service-resource')); }); - + } }); -ui.routes.push({path: "dev/resource/new", name: "newResReg", callback: - function() { - +ui.routes.push({ + path: "dev/resource/new", + name: "newResReg", + callback: function() { + this.breadCrumbView.collection.reset(); - this.breadCrumbView.collection.add([ - {text:$.t('admin.home'), href:""}, - {text:$.t('admin.self-service-resource'), href:"manage/#dev/resource"}, - {text:$.t('rsreg.new'), href:"manage/#dev/resource/new"} - ]); - - this.updateSidebar('dev/resource'); - + this.breadCrumbView.collection.add([{ + text: $.t('admin.home'), + href: "" + }, { + text: $.t('admin.self-service-resource'), + href: "manage/#dev/resource" + }, { + text: $.t('rsreg.new'), + href: "manage/#dev/resource/new" + }]); + + this.updateSidebar('dev/resource'); + var client = new ResRegClient(); - var view = new ResRegEditView({model: client, systemScopeList:this.systemScopeList}); - + var view = new ResRegEditView({ + model: client, + systemScopeList: this.systemScopeList + }); + view.load(function() { - + var userInfo = getUserInfo(); var contacts = []; if (userInfo != null && userInfo.email != null) { contacts.push(userInfo.email); } - + client.set({ - scope: _.uniq(_.flatten(app.systemScopeList.defaultUnrestrictedScopes().pluck("value"))).join(" "), - token_endpoint_auth_method: 'client_secret_basic', - contacts: contacts - }, { silent: true }); - + scope: _.uniq(_.flatten(app.systemScopeList.defaultUnrestrictedScopes().pluck("value"))).join(" "), + token_endpoint_auth_method: 'client_secret_basic', + contacts: contacts + }, { + silent: true + }); + $('#content').html(view.render().el); view.delegateEvents(); setPageTitle($.t('rsreg.new')); - + }); - + } }); -ui.routes.push({path: "dev/resource/edit", name: "editResReg", callback: - function() { +ui.routes.push({ + path: "dev/resource/edit", + name: "editResReg", + callback: function() { this.breadCrumbView.collection.reset(); - this.breadCrumbView.collection.add([ - {text:$.t('admin.home'), href:""}, - {text:$.t('admin.self-service-resource'), href:"manage/#dev/resource"}, - {text:$.t('rsreg.edit'), href:"manage/#dev/resource/edit"} - ]); - - this.updateSidebar('dev/resource'); - + this.breadCrumbView.collection.add([{ + text: $.t('admin.home'), + href: "" + }, { + text: $.t('admin.self-service-resource'), + href: "manage/#dev/resource" + }, { + text: $.t('rsreg.edit'), + href: "manage/#dev/resource/edit" + }]); + + this.updateSidebar('dev/resource'); + setPageTitle($.t('rsreg.edit')); - // note that this doesn't actually load the client, that's supposed to happen elsewhere... + // note that this doesn't actually load the client, that's supposed to + // happen elsewhere... } }); diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/scope.js b/openid-connect-server-webapp/src/main/webapp/resources/js/scope.js index aced6de280..867f89f8ad 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/scope.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/scope.js @@ -17,23 +17,23 @@ var SystemScopeModel = Backbone.Model.extend({ idAttribute: 'id', - defaults:{ - id:null, - description:null, - icon:null, - value:null, - defaultScope:false, - restricted:false + defaults: { + id: null, + description: null, + icon: null, + value: null, + defaultScope: false, + restricted: false }, - + urlRoot: 'api/scopes' }); var SystemScopeCollection = Backbone.Collection.extend({ idAttribute: 'id', - + model: SystemScopeModel, - + url: 'api/scopes', defaultScopes: function() { @@ -42,149 +42,164 @@ var SystemScopeCollection = Backbone.Collection.extend({ }); return new SystemScopeCollection(filtered); }, - + unrestrictedScopes: function() { filtered = this.filter(function(scope) { return scope.get("restricted") !== true; }); return new SystemScopeCollection(filtered); }, - + defaultUnrestrictedScopes: function() { filtered = this.filter(function(scope) { return scope.get("defaultScope") === true && scope.get("restricted") !== true; }); return new SystemScopeCollection(filtered); }, - + getByValue: function(value) { - var scopes = this.where({value: value}); + var scopes = this.where({ + value: value + }); if (scopes.length == 1) { return scopes[0]; } else { return null; } } - + }); var SystemScopeView = Backbone.View.extend({ - + tagName: 'tr', - - initialize:function (options) { - this.options = options; - - if (!this.template) { - this.template = _.template($('#tmpl-system-scope').html()); - } - - this.model.bind('change', this.render, this); - - }, - - events: { - 'click .btn-edit':'editScope', - 'click .btn-delete':'deleteScope' + + initialize: function(options) { + this.options = options; + + if (!this.template) { + this.template = _.template($('#tmpl-system-scope').html()); + } + + this.model.bind('change', this.render, this); + }, - - editScope:function(e) { - e.preventDefault(); - app.navigate('admin/scope/' + this.model.id, {trigger: true}); + + events: { + 'click .btn-edit': 'editScope', + 'click .btn-delete': 'deleteScope' }, - - render:function (eventName) { - this.$el.html(this.template(this.model.toJSON())); - - $('.restricted', this.el).tooltip({title: $.t('scope.system-scope-table.tooltip-restricted')}); - $('.default', this.el).tooltip({title: $.t('scope.system-scope-table.tooltip-default')}); - - $(this.el).i18n(); - return this; - }, - - deleteScope:function (e) { - e.preventDefault(); - - if (confirm($.t("scope.system-scope-table.confirm"))) { - var _self = this; - - this.model.destroy({ - dataType: false, processData: false, - success:function () { - - _self.$el.fadeTo("fast", 0.00, function () { //fade - $(this).slideUp("fast", function () { //slide up - $(this).remove(); //then remove from the DOM - _self.parentView.togglePlaceholder(); - }); - }); - }, - error:app.errorHandlerView.handleError() - }); - - _self.parentView.delegateEvents(); - } - - return false; - }, - - close:function () { - $(this.el).unbind(); - $(this.el).empty(); - } + + editScope: function(e) { + e.preventDefault(); + app.navigate('admin/scope/' + this.model.id, { + trigger: true + }); + }, + + render: function(eventName) { + this.$el.html(this.template(this.model.toJSON())); + + $('.restricted', this.el).tooltip({ + title: $.t('scope.system-scope-table.tooltip-restricted') + }); + $('.default', this.el).tooltip({ + title: $.t('scope.system-scope-table.tooltip-default') + }); + + $(this.el).i18n(); + return this; + }, + + deleteScope: function(e) { + e.preventDefault(); + + if (confirm($.t("scope.system-scope-table.confirm"))) { + var _self = this; + + this.model.destroy({ + dataType: false, + processData: false, + success: function() { + + _self.$el.fadeTo("fast", 0.00, function() { // fade + $(this).slideUp("fast", function() { // slide up + $(this).remove(); // then remove from the DOM + _self.parentView.togglePlaceholder(); + }); + }); + }, + error: app.errorHandlerView.handleError() + }); + + _self.parentView.delegateEvents(); + } + + return false; + }, + + close: function() { + $(this.el).unbind(); + $(this.el).empty(); + } }); var SystemScopeListView = Backbone.View.extend({ tagName: 'span', - - initialize:function(options) { - this.options = options; + + initialize: function(options) { + this.options = options; + }, + + load: function(callback) { + if (this.model.isFetched) { + callback(); + return; + } + + $('#loadingbox').sheet('show'); + $('#loading').html('' + $.t('common.scopes') + ' '); + + $.when(this.model.fetchIfNeeded({ + success: function(e) { + $('#loading-scopes').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + })).done(function() { + $('#loadingbox').sheet('hide'); + callback(); + }); }, - - load:function(callback) { - if (this.model.isFetched) { - callback(); - return; - } - - $('#loadingbox').sheet('show'); - $('#loading').html( - '' + $.t('common.scopes') + ' ' - ); - - $.when(this.model.fetchIfNeeded({success:function(e) {$('#loading-scopes').addClass('label-success');}, error:app.errorHandlerView.handleError()})) - .done(function() { - $('#loadingbox').sheet('hide'); - callback(); - }); - }, - - events:{ - "click .new-scope":"newScope", - "click .refresh-table":"refreshTable" + + events: { + "click .new-scope": "newScope", + "click .refresh-table": "refreshTable" }, - newScope:function(e) { + newScope: function(e) { this.remove(); - app.navigate('admin/scope/new', {trigger: true}); + app.navigate('admin/scope/new', { + trigger: true + }); }, - - refreshTable:function(e) { + + refreshTable: function(e) { var _self = this; - $('#loadingbox').sheet('show'); - $('#loading').html( - '' + $.t('common.scopes') + ' ' - ); - - $.when(this.model.fetch({success:function(e) {$('#loading-scopes').addClass('label-success');}, error:app.errorHandlerView.handleError()})) - .done(function() { - $('#loadingbox').sheet('hide'); - _self.render(); - }); + $('#loadingbox').sheet('show'); + $('#loading').html('' + $.t('common.scopes') + ' '); + + $.when(this.model.fetch({ + success: function(e) { + $('#loading-scopes').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + })).done(function() { + $('#loadingbox').sheet('hide'); + _self.render(); + }); }, - - togglePlaceholder:function() { + + togglePlaceholder: function() { if (this.model.length > 0) { $('#scope-table', this.el).show(); $('#scope-table-empty', this.el).hide(); @@ -193,249 +208,271 @@ var SystemScopeListView = Backbone.View.extend({ $('#scope-table-empty', this.el).show(); } }, - - render: function (eventName) { - + + render: function(eventName) { + // append and render the table structure $(this.el).html($('#tmpl-system-scope-table').html()); - + var _self = this; - - _.each(this.model.models, function (scope) { - var view = new SystemScopeView({model: scope}); + + _.each(this.model.models, function(scope) { + var view = new SystemScopeView({ + model: scope + }); view.parentView = _self; $("#scope-table", _self.el).append(view.render().el); }, this); - + this.togglePlaceholder(); - $(this.el).i18n(); + $(this.el).i18n(); return this; } }); -var SystemScopeFormView = Backbone.View.extend({ - tagName: 'span', - - initialize:function(options) { - this.options = options; - if (!this.template) { - this.template = _.template($('#tmpl-system-scope-form').html()); - } - if (!this.iconTemplate) { - this.iconTemplate = _.template($('#tmpl-system-scope-icon').html()); - } - - // initialize our icon set into slices for the selector - if (!this.bootstrapIcons) { - this.bootstrapIcons = []; - - var iconList = ['glass', 'music', 'search', 'envelope', 'heart', 'star', 'star-empty', - 'user', 'film', 'th-large', 'th', 'th-list', 'ok', 'remove', 'zoom-in', - 'zoom-out', 'off', 'signal', 'cog', 'trash', 'home', 'file', 'time', 'road', - 'download-alt', 'download', 'upload', 'inbox', 'play-circle', 'repeat', - 'refresh', 'list-alt', 'lock', 'flag', 'headphones', 'volume-off', - 'volume-down', 'volume-up', 'qrcode', 'barcode', 'tag', 'tags', 'book', - 'bookmark', 'print', 'camera', 'font', 'bold', 'italic', 'text-height', - 'text-width', 'align-left', 'align-center', 'align-right', 'align-justify', - 'list', 'indent-left', 'indent-right', 'facetime-video', 'picture', 'pencil', - 'map-marker', 'adjust', 'tint', 'edit', 'share', 'check', 'move', 'step-backward', - 'fast-backward', 'backward', 'play', 'pause', 'stop', 'forward', 'fast-forward', - 'step-forward', 'eject', 'chevron-left', 'chevron-right', 'plus-sign', - 'minus-sign', 'remove-sign', 'ok-sign', 'question-sign', 'info-sign', - 'screenshot', 'remove-circle', 'ok-circle', 'ban-circle', 'arrow-left', - 'arrow-right', 'arrow-up', 'arrow-down', 'share-alt', 'resize-full', 'resize-small', - 'plus', 'minus', 'asterisk', 'exclamation-sign', 'gift', 'leaf', 'fire', - 'eye-open', 'eye-close', 'warning-sign', 'plane', 'calendar', 'random', - 'comment', 'magnet', 'chevron-up', 'chevron-down', 'retweet', 'shopping-cart', - 'folder-close', 'folder-open', 'resize-vertical', 'resize-horizontal', - 'hdd', 'bullhorn', 'bell', 'certificate', 'thumbs-up', 'thumbs-down', - 'hand-right', 'hand-left', 'hand-up', 'hand-down', 'circle-arrow-right', - 'circle-arrow-left', 'circle-arrow-up', 'circle-arrow-down', 'globe', - 'wrench', 'tasks', 'filter', 'briefcase', 'fullscreen']; - - var size = 3; - while (iconList.length > 0) { - this.bootstrapIcons.push(iconList.splice(0, size)); - } +var SystemScopeFormView = Backbone.View + .extend({ + tagName: 'span', - } - }, - - events:{ - 'click .btn-save':'saveScope', - 'click .btn-cancel': function() {app.navigate('admin/scope', {trigger: true}); }, - 'click .btn-icon':'selectIcon' - }, - - load:function(callback) { - if (this.model.isFetched) { - callback(); - return; - } - - $('#loadingbox').sheet('show'); - $('#loading').html( - '' + $.t("common.scopes") + ' ' - ); - - $.when(this.model.fetchIfNeeded({success:function(e) {$('#loading-scopes').addClass('label-success');}, error:app.errorHandlerView.handleError()})) - .done(function() { - $('#loadingbox').sheet('hide'); - callback(); - }); - - }, - - saveScope:function(e) { - e.preventDefault(); - - var value = $('#value input').val(); - - if (value == null || value.trim() == "") { - // error: can't have a blank scope - return false; - } - - var valid = this.model.set({ - value:value, - description:$('#description textarea').val(), - icon:$('#iconDisplay input').val(), - defaultScope:$('#defaultScope input').is(':checked'), - restricted:$('#restricted input').is(':checked') - }); - - if (valid) { - - var _self = this; - this.model.save({}, { - success:function() { - app.systemScopeList.add(_self.model); - app.navigate('admin/scope', {trigger: true}); + initialize: function(options) { + this.options = options; + if (!this.template) { + this.template = _.template($('#tmpl-system-scope-form').html()); + } + if (!this.iconTemplate) { + this.iconTemplate = _.template($('#tmpl-system-scope-icon').html()); + } + + // initialize our icon set into slices for the selector + if (!this.bootstrapIcons) { + this.bootstrapIcons = []; + + var iconList = ['glass', 'music', 'search', 'envelope', 'heart', 'star', 'star-empty', 'user', 'film', 'th-large', 'th', 'th-list', 'ok', 'remove', 'zoom-in', 'zoom-out', 'off', 'signal', 'cog', 'trash', 'home', 'file', 'time', 'road', 'download-alt', 'download', 'upload', 'inbox', 'play-circle', 'repeat', 'refresh', 'list-alt', 'lock', + 'flag', 'headphones', 'volume-off', 'volume-down', 'volume-up', 'qrcode', 'barcode', 'tag', 'tags', 'book', 'bookmark', 'print', 'camera', 'font', 'bold', 'italic', 'text-height', 'text-width', 'align-left', 'align-center', 'align-right', 'align-justify', 'list', 'indent-left', 'indent-right', 'facetime-video', 'picture', + 'pencil', 'map-marker', 'adjust', 'tint', 'edit', 'share', 'check', 'move', 'step-backward', 'fast-backward', 'backward', 'play', 'pause', 'stop', 'forward', 'fast-forward', 'step-forward', 'eject', 'chevron-left', 'chevron-right', 'plus-sign', 'minus-sign', 'remove-sign', 'ok-sign', 'question-sign', 'info-sign', 'screenshot', + 'remove-circle', 'ok-circle', 'ban-circle', 'arrow-left', 'arrow-right', 'arrow-up', 'arrow-down', 'share-alt', 'resize-full', 'resize-small', 'plus', 'minus', 'asterisk', 'exclamation-sign', 'gift', 'leaf', 'fire', 'eye-open', 'eye-close', 'warning-sign', 'plane', 'calendar', 'random', 'comment', 'magnet', 'chevron-up', + 'chevron-down', 'retweet', 'shopping-cart', 'folder-close', 'folder-open', 'resize-vertical', 'resize-horizontal', 'hdd', 'bullhorn', 'bell', 'certificate', 'thumbs-up', 'thumbs-down', 'hand-right', 'hand-left', 'hand-up', 'hand-down', 'circle-arrow-right', 'circle-arrow-left', 'circle-arrow-up', 'circle-arrow-down', 'globe', + 'wrench', 'tasks', 'filter', 'briefcase', 'fullscreen']; + + var size = 3; + while (iconList.length > 0) { + this.bootstrapIcons.push(iconList.splice(0, size)); + } + + } + }, + + events: { + 'click .btn-save': 'saveScope', + 'click .btn-cancel': function() { + app.navigate('admin/scope', { + trigger: true + }); }, - error:app.errorHandlerView.handleError() - }); - } + 'click .btn-icon': 'selectIcon' + }, - return false; - }, - - selectIcon:function(e) { - e.preventDefault(); - - var icon = e.target.value; - - $('#iconDisplay input').val(icon); - $('#iconDisplay #iconName').html(icon); - $('#iconDisplay i').removeClass(); - $('#iconDisplay i').addClass('icon-' + icon); - $('#iconDisplay i').addClass('icon-white'); - - $('#iconSelector').modal('hide'); - - return false; - }, - - render: function(eventName) { - this.$el.html(this.template(this.model.toJSON())); - - _.each(this.bootstrapIcons, function (items) { - $("#iconSelector .modal-body", this.el).append(this.iconTemplate({items:items})); - }, this); - - $(this.el).i18n(); - return this; - } -}); + load: function(callback) { + if (this.model.isFetched) { + callback(); + return; + } + + $('#loadingbox').sheet('show'); + $('#loading').html('' + $.t("common.scopes") + ' '); + + $.when(this.model.fetchIfNeeded({ + success: function(e) { + $('#loading-scopes').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + })).done(function() { + $('#loadingbox').sheet('hide'); + callback(); + }); + + }, + + saveScope: function(e) { + e.preventDefault(); + + var value = $('#value input').val(); + + if (value == null || value.trim() == "") { + // error: can't have a blank scope + return false; + } + + var valid = this.model.set({ + value: value, + description: $('#description textarea').val(), + icon: $('#iconDisplay input').val(), + defaultScope: $('#defaultScope input').is(':checked'), + restricted: $('#restricted input').is(':checked') + }); + + if (valid) { + + var _self = this; + this.model.save({}, { + success: function() { + app.systemScopeList.add(_self.model); + app.navigate('admin/scope', { + trigger: true + }); + }, + error: app.errorHandlerView.handleError() + }); + } + + return false; + }, + + selectIcon: function(e) { + e.preventDefault(); + + var icon = e.target.value; + + $('#iconDisplay input').val(icon); + $('#iconDisplay #iconName').html(icon); + $('#iconDisplay i').removeClass(); + $('#iconDisplay i').addClass('icon-' + icon); + $('#iconDisplay i').addClass('icon-white'); + + $('#iconSelector').modal('hide'); + + return false; + }, + + render: function(eventName) { + this.$el.html(this.template(this.model.toJSON())); + + _.each(this.bootstrapIcons, function(items) { + $("#iconSelector .modal-body", this.el).append(this.iconTemplate({ + items: items + })); + }, this); + + $(this.el).i18n(); + return this; + } + }); + +ui.routes.push({ + path: "admin/scope", + name: "siteScope", + callback: function() { -ui.routes.push({path: "admin/scope", name: "siteScope", callback: - function() { - if (!isAdmin()) { this.root(); return; } - + this.breadCrumbView.collection.reset(); - this.breadCrumbView.collection.add([ - {text:$.t('admin.home'), href:""}, - {text:$.t('scope.manage'), href:"manage/#admin/scope"} - ]); - - this.updateSidebar('admin/scope'); - - var view = new SystemScopeListView({model:this.systemScopeList}); - + this.breadCrumbView.collection.add([{ + text: $.t('admin.home'), + href: "" + }, { + text: $.t('scope.manage'), + href: "manage/#admin/scope" + }]); + + this.updateSidebar('admin/scope'); + + var view = new SystemScopeListView({ + model: this.systemScopeList + }); + view.load(function() { $('#content').html(view.render().el); view.delegateEvents(); - setPageTitle($.t('scope.manage')); + setPageTitle($.t('scope.manage')); }); - + } }); -ui.routes.push({path: "admin/scope/new", name:"newScope", callback: - function() { - - +ui.routes.push({ + path: "admin/scope/new", + name: "newScope", + callback: function() { + if (!isAdmin()) { this.root(); return; } - + this.breadCrumbView.collection.reset(); - this.breadCrumbView.collection.add([ - {text:$.t('admin.home'), href:""}, - {text:$.t('scope.manage'), href:"manage/#admin/scope"}, - {text:$.t('scope.system-scope-form.new'), href:"manage/#admin/scope/new"} - ]); - - this.updateSidebar('admin/scope'); - + this.breadCrumbView.collection.add([{ + text: $.t('admin.home'), + href: "" + }, { + text: $.t('scope.manage'), + href: "manage/#admin/scope" + }, { + text: $.t('scope.system-scope-form.new'), + href: "manage/#admin/scope/new" + }]); + + this.updateSidebar('admin/scope'); + var scope = new SystemScopeModel(); - - var view = new SystemScopeFormView({model:scope}); + + var view = new SystemScopeFormView({ + model: scope + }); view.load(function() { $('#content').html(view.render().el); setPageTitle($.t('scope.system-scope-form.new')); }); - + } }); -ui.routes.push({path: "admin/scope/:id", name: "editScope", callback: - function(sid) { +ui.routes.push({ + path: "admin/scope/:id", + name: "editScope", + callback: function(sid) { if (!isAdmin()) { this.root(); return; } - + this.breadCrumbView.collection.reset(); - this.breadCrumbView.collection.add([ - {text:$.t('admin.home'), href:""}, - {text:$.t('scope.manage'), href:"manage/#admin/scope"}, - {text:$.t('scope.system-scope-form.edit'), href:"manage/#admin/scope/" + sid} - ]); - - this.updateSidebar('admin/scope'); - + this.breadCrumbView.collection.add([{ + text: $.t('admin.home'), + href: "" + }, { + text: $.t('scope.manage'), + href: "manage/#admin/scope" + }, { + text: $.t('scope.system-scope-form.edit'), + href: "manage/#admin/scope/" + sid + }]); + + this.updateSidebar('admin/scope'); + var scope = this.systemScopeList.get(sid); if (!scope) { - scope = new SystemScopeModel({id: sid}); + scope = new SystemScopeModel({ + id: sid + }); } - - var view = new SystemScopeFormView({model:scope}); + + var view = new SystemScopeFormView({ + model: scope + }); view.load(function() { $('#content').html(view.render().el); setPageTitle($.t('scope.system-scope-form.new')); }); - + } }); ui.templates.push('resources/template/scope.html'); ui.init.push(function(app) { - app.systemScopeList = new SystemScopeCollection(); + app.systemScopeList = new SystemScopeCollection(); }); diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/token.js b/openid-connect-server-webapp/src/main/webapp/resources/js/token.js index ed012a620a..36112eb3c3 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/token.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/token.js @@ -18,59 +18,59 @@ var AccessTokenModel = Backbone.Model.extend({ idAttribute: 'id', - defaults:{ - id:null, - value:null, - refreshTokenId:null, - scopes:[], - clientId:null, - userId:null, - expiration:null + defaults: { + id: null, + value: null, + refreshTokenId: null, + scopes: [], + clientId: null, + userId: null, + expiration: null }, - + urlRoot: 'api/tokens/access' }); var AccessTokenCollection = Backbone.Collection.extend({ idAttribute: 'id', - + model: AccessTokenModel, - + url: 'api/tokens/access' - + }); var AccessTokenView = Backbone.View.extend({ - + tagName: 'tr', - - initialize:function (options) { - this.options = options; - - if (!this.template) { - this.template = _.template($('#tmpl-access-token').html()); - } - - if (!this.scopeTemplate) { - this.scopeTemplate = _.template($('#tmpl-scope-list').html()); - } - - if (!this.moreInfoTemplate) { - this.moreInfoTemplate = _.template($('#tmpl-client-more-info-block').html()); - } - - this.model.bind('change', this.render, this); - - }, - - events: { - 'click .btn-delete':'deleteToken', - 'click .token-substring':'showTokenValue', + + initialize: function(options) { + this.options = options; + + if (!this.template) { + this.template = _.template($('#tmpl-access-token').html()); + } + + if (!this.scopeTemplate) { + this.scopeTemplate = _.template($('#tmpl-scope-list').html()); + } + + if (!this.moreInfoTemplate) { + this.moreInfoTemplate = _.template($('#tmpl-client-more-info-block').html()); + } + + this.model.bind('change', this.render, this); + + }, + + events: { + 'click .btn-delete': 'deleteToken', + 'click .token-substring': 'showTokenValue', 'click .toggleMoreInformation': 'toggleMoreInformation' }, - - render:function (eventName) { - + + render: function(eventName) { + var expirationDate = this.model.get("expiration"); if (expirationDate == null) { @@ -80,59 +80,70 @@ var AccessTokenView = Backbone.View.extend({ } else { expirationDate = moment(expirationDate).calendar(); } - - var json = {token: this.model.toJSON(), client: this.options.client.toJSON(), formattedExpiration: expirationDate}; + + var json = { + token: this.model.toJSON(), + client: this.options.client.toJSON(), + formattedExpiration: expirationDate + }; this.$el.html(this.template(json)); // hide full value - $('.token-full', this.el).hide(); - + $('.token-full', this.el).hide(); + // show scopes - $('.scope-list', this.el).html(this.scopeTemplate({scopes: this.model.get('scopes'), systemScopes: this.options.systemScopeList})); - - $('.client-more-info-block', this.el).html(this.moreInfoTemplate({client: this.options.client.toJSON()})); - - $(this.el).i18n(); - return this; - }, - - deleteToken:function (e) { - e.preventDefault(); - - if (confirm($.t("token.token-table.confirm"))) { - - var _self = this; - - this.model.destroy({ - dataType: false, processData: false, - success:function () { - - _self.$el.fadeTo("fast", 0.00, function () { //fade - $(this).slideUp("fast", function () { //slide up - $(this).remove(); //then remove from the DOM - // refresh the table in case we removed an id token, too - _self.parentView.refreshTable(); - }); - }); - }, - error:app.errorHandlerView.handleError() - }); - - this.parentView.delegateEvents(); - } - - return false; - }, - - toggleMoreInformation:function(e) { + $('.scope-list', this.el).html(this.scopeTemplate({ + scopes: this.model.get('scopes'), + systemScopes: this.options.systemScopeList + })); + + $('.client-more-info-block', this.el).html(this.moreInfoTemplate({ + client: this.options.client.toJSON() + })); + + $(this.el).i18n(); + return this; + }, + + deleteToken: function(e) { + e.preventDefault(); + + if (confirm($.t("token.token-table.confirm"))) { + + var _self = this; + + this.model.destroy({ + dataType: false, + processData: false, + success: function() { + + _self.$el.fadeTo("fast", 0.00, function() { // fade + $(this).slideUp("fast", function() { // slide up + $(this).remove(); // then remove from the DOM + // refresh the table in case we removed an id token, + // too + _self.parentView.refreshTable(); + }); + }); + }, + error: app.errorHandlerView.handleError() + }); + + this.parentView.delegateEvents(); + } + + return false; + }, + + toggleMoreInformation: function(e) { e.preventDefault(); if ($('.moreInformation', this.el).is(':visible')) { // hide it $('.moreInformation', this.el).hide('fast'); $('.toggleMoreInformation i', this.el).attr('class', 'icon-chevron-right'); $('.moreInformationContainer', this.el).removeClass('alert').removeClass('alert-info').addClass('muted'); - + } else { // show it $('.moreInformation', this.el).show('fast'); @@ -141,73 +152,73 @@ var AccessTokenView = Backbone.View.extend({ } }, - close:function () { - $(this.el).unbind(); - $(this.el).empty(); - }, - - showTokenValue:function (e) { - e.preventDefault(); - $('.token-substring', this.el).hide(); - $('.token-full', this.el).show(); - } + close: function() { + $(this.el).unbind(); + $(this.el).empty(); + }, + + showTokenValue: function(e) { + e.preventDefault(); + $('.token-substring', this.el).hide(); + $('.token-full', this.el).show(); + } }); var RefreshTokenModel = Backbone.Model.extend({ idAttribute: 'id', - defaults:{ - id:null, - value:null, - scopes:[], - clientId:null, - userId:null, - expiration:null + defaults: { + id: null, + value: null, + scopes: [], + clientId: null, + userId: null, + expiration: null }, - + urlRoot: 'api/tokens/refresh' }); var RefreshTokenCollection = Backbone.Collection.extend({ idAttribute: 'id', - + model: RefreshTokenModel, - + url: 'api/tokens/refresh' - + }); var RefreshTokenView = Backbone.View.extend({ - + tagName: 'tr', - - initialize:function (options) { - this.options = options; - - if (!this.template) { - this.template = _.template($('#tmpl-refresh-token').html()); - } - - if (!this.scopeTemplate) { - this.scopeTemplate = _.template($('#tmpl-scope-list').html()); - } - - if (!this.moreInfoTemplate) { - this.moreInfoTemplate = _.template($('#tmpl-client-more-info-block').html()); - } - - this.model.bind('change', this.render, this); - - }, - - events: { - 'click .btn-delete':'deleteToken', - 'click .token-substring':'showTokenValue', + + initialize: function(options) { + this.options = options; + + if (!this.template) { + this.template = _.template($('#tmpl-refresh-token').html()); + } + + if (!this.scopeTemplate) { + this.scopeTemplate = _.template($('#tmpl-scope-list').html()); + } + + if (!this.moreInfoTemplate) { + this.moreInfoTemplate = _.template($('#tmpl-client-more-info-block').html()); + } + + this.model.bind('change', this.render, this); + + }, + + events: { + 'click .btn-delete': 'deleteToken', + 'click .token-substring': 'showTokenValue', 'click .toggleMoreInformation': 'toggleMoreInformation' }, - - render:function (eventName) { - + + render: function(eventName) { + var expirationDate = this.model.get("expiration"); if (expirationDate == null) { @@ -217,53 +228,65 @@ var RefreshTokenView = Backbone.View.extend({ } else { expirationDate = moment(expirationDate).calendar(); } - - var json = {token: this.model.toJSON(), client: this.options.client.toJSON(), formattedExpiration: expirationDate, accessTokenCount: this.options.accessTokenCount}; + + var json = { + token: this.model.toJSON(), + client: this.options.client.toJSON(), + formattedExpiration: expirationDate, + accessTokenCount: this.options.accessTokenCount + }; this.$el.html(this.template(json)); // hide full value - $('.token-full', this.el).hide(); - + $('.token-full', this.el).hide(); + // show scopes - $('.scope-list', this.el).html(this.scopeTemplate({scopes: this.model.get('scopes'), systemScopes: this.options.systemScopeList})); - - $('.client-more-info-block', this.el).html(this.moreInfoTemplate({client: this.options.client.toJSON()})); - - $(this.el).i18n(); - return this; - - }, - - deleteToken:function (e) { - e.preventDefault(); - - if (confirm($.t('token.token-table.confirm-refresh'))) { - - var _self = this; - - this.model.destroy({ - dataType: false, processData: false, - success:function () { - - _self.$el.fadeTo("fast", 0.00, function () { //fade - $(this).slideUp("fast", function () { //slide up - $(this).remove(); //then remove from the DOM - // refresh the table in case the access tokens have changed, too - _self.parentView.refreshTable(); - }); - }); - }, - error:app.errorHandlerView.handleError() - }); - - _self.parentView.delegateEvents(); - } - - return false; - }, - - toggleMoreInformation:function(e) { + $('.scope-list', this.el).html(this.scopeTemplate({ + scopes: this.model.get('scopes'), + systemScopes: this.options.systemScopeList + })); + + $('.client-more-info-block', this.el).html(this.moreInfoTemplate({ + client: this.options.client.toJSON() + })); + + $(this.el).i18n(); + return this; + + }, + + deleteToken: function(e) { + e.preventDefault(); + + if (confirm($.t('token.token-table.confirm-refresh'))) { + + var _self = this; + + this.model.destroy({ + dataType: false, + processData: false, + success: function() { + + _self.$el.fadeTo("fast", 0.00, function() { // fade + $(this).slideUp("fast", function() { // slide up + $(this).remove(); // then remove from the DOM + // refresh the table in case the access tokens have + // changed, too + _self.parentView.refreshTable(); + }); + }); + }, + error: app.errorHandlerView.handleError() + }); + + _self.parentView.delegateEvents(); + } + + return false; + }, + + toggleMoreInformation: function(e) { e.preventDefault(); if ($('.moreInformation', this.el).is(':visible')) { // hide it @@ -279,101 +302,128 @@ var RefreshTokenView = Backbone.View.extend({ }, - close:function () { - $(this.el).unbind(); - $(this.el).empty(); - }, - - showTokenValue:function (e) { - e.preventDefault(); - $('.token-substring', this.el).hide(); - $('.token-full', this.el).show(); - } + close: function() { + $(this.el).unbind(); + $(this.el).empty(); + }, + + showTokenValue: function(e) { + e.preventDefault(); + $('.token-substring', this.el).hide(); + $('.token-full', this.el).show(); + } }); var TokenListView = Backbone.View.extend({ tagName: 'span', - - initialize:function(options) { - this.options = options; + + initialize: function(options) { + this.options = options; }, - - events:{ - "click .refresh-table":"refreshTable", - 'page .paginator-access':'changePageAccess', - 'page .paginator-refresh':'changePageRefresh' + + events: { + "click .refresh-table": "refreshTable", + 'page .paginator-access': 'changePageAccess', + 'page .paginator-refresh': 'changePageRefresh' }, - load:function(callback) { - if (this.model.access.isFetched && - this.model.refresh.isFetched && - this.options.clientList.isFetched && - this.options.systemScopeList.isFetched) { - callback(); - return; - } - - $('#loadingbox').sheet('show'); - $('#loading').html( - '' + $.t('token.token-table.access-tokens') + ' ' + - '' + $.t('token.token-table.refresh-tokens') + ' ' + - '' + $.t('common.clients') + ' ' + - '' + $.t('common.scopes') + ' ' - ); - - $.when(this.model.access.fetchIfNeeded({success:function(e) {$('#loading-access').addClass('label-success');}, error: app.errorHandlerView.handleError()}), - this.model.refresh.fetchIfNeeded({success:function(e) {$('#loading-refresh').addClass('label-success');}, error: app.errorHandlerView.handleError()}), - this.options.clientList.fetchIfNeeded({success:function(e) {$('#loading-clients').addClass('label-success');}, error: app.errorHandlerView.handleError()}), - this.options.systemScopeList.fetchIfNeeded({success:function(e) {$('#loading-scopes').addClass('label-success');}, error: app.errorHandlerView.handleError()})) - .done(function() { - $('#loadingbox').sheet('hide'); - callback(); - }); - - }, - - changePageAccess:function(event, num) { - $('.paginator-access', this.el).bootpag({page: num}); + load: function(callback) { + if (this.model.access.isFetched && this.model.refresh.isFetched && this.options.clientList.isFetched && this.options.systemScopeList.isFetched) { + callback(); + return; + } + + $('#loadingbox').sheet('show'); + $('#loading').html( + '' + $.t('token.token-table.access-tokens') + ' ' + '' + $.t('token.token-table.refresh-tokens') + ' ' + '' + $.t('common.clients') + ' ' + '' + + $.t('common.scopes') + ' '); + + $.when(this.model.access.fetchIfNeeded({ + success: function(e) { + $('#loading-access').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + }), this.model.refresh.fetchIfNeeded({ + success: function(e) { + $('#loading-refresh').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + }), this.options.clientList.fetchIfNeeded({ + success: function(e) { + $('#loading-clients').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + }), this.options.systemScopeList.fetchIfNeeded({ + success: function(e) { + $('#loading-scopes').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + })).done(function() { + $('#loadingbox').sheet('hide'); + callback(); + }); + + }, + + changePageAccess: function(event, num) { + $('.paginator-access', this.el).bootpag({ + page: num + }); $('#access-token-table tbody tr', this.el).each(function(index, element) { if (Math.ceil((index + 1) / 10) != num) { - $(element).hide(); - } else { - $(element).show(); - } + $(element).hide(); + } else { + $(element).show(); + } }); }, - - changePageRefresh:function(event, num) { - $('.paginator-refresh', this.el).bootpag({page: num}); + + changePageRefresh: function(event, num) { + $('.paginator-refresh', this.el).bootpag({ + page: num + }); $('#refresh-token-table tbody tr', this.el).each(function(index, element) { if (Math.ceil((index + 1) / 10) != num) { - $(element).hide(); - } else { - $(element).show(); - } + $(element).hide(); + } else { + $(element).show(); + } }); }, - - refreshTable:function(e) { - $('#loadingbox').sheet('show'); - $('#loading').html( - '' + $.t('token.token-table.access-tokens') + ' ' + - '' + $.t('token.token-table.refresh-tokens') + ' ' + - '' + $.t('common.clients') + ' ' + - '' + $.t('common.scopes') + ' ' - ); - var _self = this; - $.when(this.model.access.fetch({success:function(e) {$('#loading-access').addClass('label-success');}, error: app.errorHandlerView.handleError()}), - this.model.refresh.fetch({success:function(e) {$('#loading-refresh').addClass('label-success');}, error: app.errorHandlerView.handleError()}), - this.options.clientList.fetch({success:function(e) {$('#loading-clients').addClass('label-success');}, error: app.errorHandlerView.handleError()}), - this.options.systemScopeList.fetch({success:function(e) {$('#loading-scopes').addClass('label-success');}, error: app.errorHandlerView.handleError()})) - .done(function(){ - _self.render(); - $('#loadingbox').sheet('hide'); - }); + + refreshTable: function(e) { + $('#loadingbox').sheet('show'); + $('#loading').html( + '' + $.t('token.token-table.access-tokens') + ' ' + '' + $.t('token.token-table.refresh-tokens') + ' ' + '' + $.t('common.clients') + ' ' + '' + + $.t('common.scopes') + ' '); + var _self = this; + $.when(this.model.access.fetch({ + success: function(e) { + $('#loading-access').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + }), this.model.refresh.fetch({ + success: function(e) { + $('#loading-refresh').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + }), this.options.clientList.fetch({ + success: function(e) { + $('#loading-clients').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + }), this.options.systemScopeList.fetch({ + success: function(e) { + $('#loading-scopes').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + })).done(function() { + _self.render(); + $('#loadingbox').sheet('hide'); + }); }, - - togglePlaceholder:function() { + + togglePlaceholder: function() { if (this.model.access.length > 0) { $('#access-token-table', this.el).show(); $('#access-token-table-empty', this.el).hide(); @@ -388,122 +438,140 @@ var TokenListView = Backbone.View.extend({ $('#refresh-token-table', this.el).hide(); $('#refresh-token-table-empty', this.el).show(); } - + $('#access-token-count', this.el).html(this.model.access.length); $('#refresh-token-count', this.el).html(this.model.refresh.length); }, - - render: function (eventName) { - + + render: function(eventName) { + // append and render the table structure $(this.el).html($('#tmpl-token-table').html()); - + var _self = this; - - // set up pagination - var numPagesAccess = Math.ceil(this.model.access.length / 10); - if (numPagesAccess > 1) { - $('.paginator-access', this.el).show(); - $('.paginator-access', this.el).bootpag({ - total: numPagesAccess, - page: 1 - }); - } else { - $('.paginator-access', this.el).hide(); - } - - // count up refresh tokens - var refreshCount = {}; - - _.each(this.model.access.models, function (token, index) { + + // set up pagination + var numPagesAccess = Math.ceil(this.model.access.length / 10); + if (numPagesAccess > 1) { + $('.paginator-access', this.el).show(); + $('.paginator-access', this.el).bootpag({ + total: numPagesAccess, + page: 1 + }); + } else { + $('.paginator-access', this.el).hide(); + } + + // count up refresh tokens + var refreshCount = {}; + + _.each(this.model.access.models, function(token, index) { // look up client var client = _self.options.clientList.getByClientId(token.get('clientId')); - var view = new AccessTokenView({model: token, client: client, systemScopeList: _self.options.systemScopeList}); + var view = new AccessTokenView({ + model: token, + client: client, + systemScopeList: _self.options.systemScopeList + }); view.parentView = _self; var element = view.render().el; $('#access-token-table', _self.el).append(element); - if (Math.ceil((index + 1) / 10) != 1) { - $(element).hide(); - } - - //console.log(token.get('refreshTokenId')); - var refId = token.get('refreshTokenId'); - if (refId != null) { - if (refreshCount[refId]) { - refreshCount[refId] += 1; - } else { - refreshCount[refId] = 1; - } - - } + if (Math.ceil((index + 1) / 10) != 1) { + $(element).hide(); + } + + // console.log(token.get('refreshTokenId')); + var refId = token.get('refreshTokenId'); + if (refId != null) { + if (refreshCount[refId]) { + refreshCount[refId] += 1; + } else { + refreshCount[refId] = 1; + } + + } }); - //console.log(refreshCount); - - // set up pagination - var numPagesRefresh = Math.ceil(this.model.refresh.length / 10); - if (numPagesRefresh > 1) { - $('.paginator-refresh', this.el).show(); - $('.paginator-refresh', this.el).bootpag({ - total: numPagesRefresh, - page: 1 - }); - } else { - $('.paginator-refresh', this.el).hide(); - } - - _.each(this.model.refresh.models, function (token, index) { + // console.log(refreshCount); + + // set up pagination + var numPagesRefresh = Math.ceil(this.model.refresh.length / 10); + if (numPagesRefresh > 1) { + $('.paginator-refresh', this.el).show(); + $('.paginator-refresh', this.el).bootpag({ + total: numPagesRefresh, + page: 1 + }); + } else { + $('.paginator-refresh', this.el).hide(); + } + + _.each(this.model.refresh.models, function(token, index) { // look up client var client = _self.options.clientList.getByClientId(token.get('clientId')); - var view = new RefreshTokenView({model: token, client: client, systemScopeList: _self.options.systemScopeList, accessTokenCount: refreshCount[token.get('id')]}); + var view = new RefreshTokenView({ + model: token, + client: client, + systemScopeList: _self.options.systemScopeList, + accessTokenCount: refreshCount[token.get('id')] + }); view.parentView = _self; var element = view.render().el; $('#refresh-token-table', _self.el).append(element); - if (Math.ceil((index + 1) / 10) != 1) { - $(element).hide(); - } + if (Math.ceil((index + 1) / 10) != 1) { + $(element).hide(); + } }); - -/* - _.each(this.model.models, function (scope) { - $("#scope-table", this.el).append(new SystemScopeView({model: scope}).render().el); - }, this); -*/ - + + /* + * _.each(this.model.models, function (scope) { $("#scope-table", + * this.el).append(new SystemScopeView({model: scope}).render().el); }, + * this); + */ + this.togglePlaceholder(); - $(this.el).i18n(); + $(this.el).i18n(); return this; } }); - -ui.routes.push({path: "user/tokens", name: "tokens", callback: - function() { +ui.routes.push({ + path: "user/tokens", + name: "tokens", + callback: function() { this.breadCrumbView.collection.reset(); - this.breadCrumbView.collection.add([ - {text:$.t('admin.home'), href:""}, - {text:$.t('token.manage'), href:"manage/#user/tokens"} - ]); - - this.updateSidebar('user/tokens'); - - var view = new TokenListView({model: {access: this.accessTokensList, refresh: this.refreshTokensList}, clientList: this.clientList, systemScopeList: this.systemScopeList}); - - view.load( - function(collection, response, options) { - $('#content').html(view.render().el); - setPageTitle($.t('token.manage')); - } - ); - + this.breadCrumbView.collection.add([{ + text: $.t('admin.home'), + href: "" + }, { + text: $.t('token.manage'), + href: "manage/#user/tokens" + }]); + + this.updateSidebar('user/tokens'); + + var view = new TokenListView({ + model: { + access: this.accessTokensList, + refresh: this.refreshTokensList + }, + clientList: this.clientList, + systemScopeList: this.systemScopeList + }); + + view.load(function(collection, response, options) { + $('#content').html(view.render().el); + setPageTitle($.t('token.manage')); + }); + } }); ui.templates.push('resources/template/token.html'); ui.init.push(function(app) { - app.accessTokensList = new AccessTokenCollection(); - app.refreshTokensList = new RefreshTokenCollection(); + app.accessTokensList = new AccessTokenCollection(); + app.refreshTokensList = new RefreshTokenCollection(); }); diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/whitelist.js b/openid-connect-server-webapp/src/main/webapp/resources/js/whitelist.js index 8441bdebdd..293bf669e3 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/whitelist.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/whitelist.js @@ -15,94 +15,107 @@ * limitations under the License. *******************************************************************************/ var WhiteListModel = Backbone.Model.extend({ - + idAttribute: "id", - - initialize: function () { }, - + + initialize: function() { + }, + urlRoot: "api/whitelist" - + }); var WhiteListCollection = Backbone.Collection.extend({ initialize: function() { - //this.fetch(); + // this.fetch(); }, - - getByClientId: function(clientId) { - var clients = this.where({clientId: clientId}); + + getByClientId: function(clientId) { + var clients = this.where({ + clientId: clientId + }); if (clients.length == 1) { return clients[0]; } else { return null; } - }, - + }, + model: WhiteListModel, url: "api/whitelist" - + }); var WhiteListListView = Backbone.View.extend({ tagName: 'span', - - initialize:function (options) { - this.options = options; + + initialize: function(options) { + this.options = options; }, - load:function(callback) { - if (this.model.isFetched && - this.options.clientList.isFetched && - this.options.systemScopeList.isFetched) { - callback(); - return; - } - - $('#loadingbox').sheet('show'); - $('#loading').html( - '' + $.t('whitelist.whitelist') + ' ' + - '' + $.t('common.clients') + ' ' + - '' + $.t('common.scopes') + ' ' - ); - - $.when(this.model.fetchIfNeeded({success:function(e) {$('#loading-whitelist').addClass('label-success');}, error: app.errorHandlerView.handleError()}), - this.options.clientList.fetchIfNeeded({success:function(e) {$('#loading-clients').addClass('label-success');}, error: app.errorHandlerView.handleError()}), - this.options.systemScopeList.fetchIfNeeded({success:function(e) {$('#loading-scopes').addClass('label-success');}, error: app.errorHandlerView.handleError()})) - .done(function() { - $('#loadingbox').sheet('hide'); - callback(); - }); - }, - - events:{ - "click .refresh-table":"refreshTable" + load: function(callback) { + if (this.model.isFetched && this.options.clientList.isFetched && this.options.systemScopeList.isFetched) { + callback(); + return; + } + + $('#loadingbox').sheet('show'); + $('#loading').html('' + $.t('whitelist.whitelist') + ' ' + '' + $.t('common.clients') + ' ' + '' + $.t('common.scopes') + ' '); + + $.when(this.model.fetchIfNeeded({ + success: function(e) { + $('#loading-whitelist').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + }), this.options.clientList.fetchIfNeeded({ + success: function(e) { + $('#loading-clients').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + }), this.options.systemScopeList.fetchIfNeeded({ + success: function(e) { + $('#loading-scopes').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + })).done(function() { + $('#loadingbox').sheet('hide'); + callback(); + }); }, - - render:function (eventName) { + + events: { + "click .refresh-table": "refreshTable" + }, + + render: function(eventName) { $(this.el).html($('#tmpl-whitelist-table').html()); - + var _self = this; - - _.each(this.model.models, function (whiteList) { - + + _.each(this.model.models, function(whiteList) { + // look up client var client = _self.options.clientList.getByClientId(whiteList.get('clientId')); - + // if there's no client ID, this is an error! if (client != null) { - var view = new WhiteListView({model: whiteList, client: client, systemScopeList: _self.options.systemScopeList}); + var view = new WhiteListView({ + model: whiteList, + client: client, + systemScopeList: _self.options.systemScopeList + }); view.parentView = _self; $('#whitelist-table', _self.el).append(view.render().el); } - + }, this); this.togglePlaceholder(); - $(this.el).i18n(); + $(this.el).i18n(); return this; }, - togglePlaceholder:function() { + togglePlaceholder: function() { if (this.model.length > 0) { $('#whitelist-table', this.el).show(); $('#whitelist-table-empty', this.el).hide(); @@ -111,108 +124,129 @@ var WhiteListListView = Backbone.View.extend({ $('#whitelist-table-empty', this.el).show(); } }, - - refreshTable:function(e) { - e.preventDefault(); - var _self = this; - $('#loadingbox').sheet('show'); - $('#loading').html( - '' + $.t('whitelist.whitelist') + ' ' + - '' + $.t('common.clients') + ' ' + - '' + $.t('common.scopes') + ' ' - ); - - $.when(this.model.fetch({success:function(e) {$('#loading-whitelist').addClass('label-success');}, error: app.errorHandlerView.handleError()}), - this.options.clientList.fetch({success:function(e) {$('#loading-clients').addClass('label-success');}, error: app.errorHandlerView.handleError()}), - this.options.systemScopeList.fetch({success:function(e) {$('#loading-scopes').addClass('label-success');}, error: app.errorHandlerView.handleError()})) - .done(function() { - $('#loadingbox').sheet('hide'); - _self.render(); - }); - } + + refreshTable: function(e) { + e.preventDefault(); + var _self = this; + $('#loadingbox').sheet('show'); + $('#loading').html('' + $.t('whitelist.whitelist') + ' ' + '' + $.t('common.clients') + ' ' + '' + $.t('common.scopes') + ' '); + + $.when(this.model.fetch({ + success: function(e) { + $('#loading-whitelist').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + }), this.options.clientList.fetch({ + success: function(e) { + $('#loading-clients').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + }), this.options.systemScopeList.fetch({ + success: function(e) { + $('#loading-scopes').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + })).done(function() { + $('#loadingbox').sheet('hide'); + _self.render(); + }); + } }); var WhiteListView = Backbone.View.extend({ tagName: 'tr', - - initialize:function(options) { - this.options = options; + + initialize: function(options) { + this.options = options; if (!this.template) { this.template = _.template($('#tmpl-whitelist').html()); } - - if (!this.scopeTemplate) { - this.scopeTemplate = _.template($('#tmpl-scope-list').html()); - } - if (!this.moreInfoTemplate) { - this.moreInfoTemplate = _.template($('#tmpl-client-more-info-block').html()); - } + if (!this.scopeTemplate) { + this.scopeTemplate = _.template($('#tmpl-scope-list').html()); + } + + if (!this.moreInfoTemplate) { + this.moreInfoTemplate = _.template($('#tmpl-client-more-info-block').html()); + } this.model.bind('change', this.render, this); }, - - render:function(eventName) { - - var json = {whiteList: this.model.toJSON(), client: this.options.client.toJSON()}; - + + render: function(eventName) { + + var json = { + whiteList: this.model.toJSON(), + client: this.options.client.toJSON() + }; + this.$el.html(this.template(json)); - $('.scope-list', this.el).html(this.scopeTemplate({scopes: this.model.get('allowedScopes'), systemScopes: this.options.systemScopeList})); - - $('.client-more-info-block', this.el).html(this.moreInfoTemplate({client: this.options.client.toJSON()})); - - this.$('.dynamically-registered').tooltip({title: $.t('common.dynamically-registered')}); + $('.scope-list', this.el).html(this.scopeTemplate({ + scopes: this.model.get('allowedScopes'), + systemScopes: this.options.systemScopeList + })); + + $('.client-more-info-block', this.el).html(this.moreInfoTemplate({ + client: this.options.client.toJSON() + })); + + this.$('.dynamically-registered').tooltip({ + title: $.t('common.dynamically-registered') + }); - $(this.el).i18n(); - return this; + $(this.el).i18n(); + return this; }, - - events:{ + + events: { 'click .btn-edit': 'editWhitelist', 'click .btn-delete': 'deleteWhitelist', 'click .toggleMoreInformation': 'toggleMoreInformation' }, - - editWhitelist:function(e) { - e.preventDefault(); - app.navigate('admin/whitelist/' + this.model.get('id'), {trigger: true}); + + editWhitelist: function(e) { + e.preventDefault(); + app.navigate('admin/whitelist/' + this.model.get('id'), { + trigger: true + }); }, - - deleteWhitelist:function(e) { - e.preventDefault(); - + + deleteWhitelist: function(e) { + e.preventDefault(); + if (confirm($.t('whitelist.confirm'))) { var _self = this; - - this.model.destroy({ - dataType: false, processData: false, - success:function () { - _self.$el.fadeTo("fast", 0.00, function () { //fade - $(this).slideUp("fast", function () { //slide up - $(this).remove(); //then remove from the DOM - // check the placeholder in case it's empty now - _self.parentView.togglePlaceholder(); - }); - }); - }, - error:app.errorHandlerView.handleError() - }); - - _self.parentView.delegateEvents(); + + this.model.destroy({ + dataType: false, + processData: false, + success: function() { + _self.$el.fadeTo("fast", 0.00, function() { // fade + $(this).slideUp("fast", function() { // slide up + $(this).remove(); // then remove from the DOM + // check the placeholder in case it's empty now + _self.parentView.togglePlaceholder(); + }); + }); + }, + error: app.errorHandlerView.handleError() + }); + + _self.parentView.delegateEvents(); } - + return false; }, - - toggleMoreInformation:function(e) { + + toggleMoreInformation: function(e) { e.preventDefault(); if ($('.moreInformation', this.el).is(':visible')) { // hide it $('.moreInformation', this.el).hide('fast'); $('.toggleMoreInformation i', this.el).attr('class', 'icon-chevron-right'); $('.moreInformationContainer', this.el).removeClass('alert').removeClass('alert-info').addClass('muted'); - + } else { // show it $('.moreInformation', this.el).show('fast'); @@ -221,7 +255,7 @@ var WhiteListView = Backbone.View.extend({ } }, - close:function() { + close: function() { $(this.el).unbind(); $(this.el).empty(); } @@ -229,278 +263,333 @@ var WhiteListView = Backbone.View.extend({ var WhiteListFormView = Backbone.View.extend({ tagName: 'span', - - initialize:function (options) { - this.options = options; + + initialize: function(options) { + this.options = options; if (!this.template) { this.template = _.template($('#tmpl-whitelist-form').html()); } - + this.scopeCollection = new Backbone.Collection(); this.listWidgetViews = []; - + }, - load:function(callback) { + load: function(callback) { if (this.options.client) { // we know what client we're dealing with already - if (this.model.isFetched && - this.options.client.isFetched) { - callback(); - return; - } - - $('#loadingbox').sheet('show'); - $('#loading').html( - '' + $.t('whitelist.whitelist') + ' ' + - '' + $.t('common.clients') + ' ' + - '' + $.t('common.scopes') + ' ' - ); - - $.when(this.model.fetchIfNeeded({success:function(e) {$('#loading-whitelist').addClass('label-success');}, error: app.errorHandlerView.handleError()}), - this.options.client.fetchIfNeeded({success:function(e) {$('#loading-clients').addClass('label-success');}, error: app.errorHandlerView.handleError()}), - this.options.systemScopeList.fetchIfNeeded({success:function(e) {$('#loading-scopes').addClass('label-success');}, error: app.errorHandlerView.handleError()})) - .done(function() { - $('#loadingbox').sheet('hide'); - callback(); - }); - + if (this.model.isFetched && this.options.client.isFetched) { + callback(); + return; + } + + $('#loadingbox').sheet('show'); + $('#loading').html('' + $.t('whitelist.whitelist') + ' ' + '' + $.t('common.clients') + ' ' + '' + $.t('common.scopes') + ' '); + + $.when(this.model.fetchIfNeeded({ + success: function(e) { + $('#loading-whitelist').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + }), this.options.client.fetchIfNeeded({ + success: function(e) { + $('#loading-clients').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + }), this.options.systemScopeList.fetchIfNeeded({ + success: function(e) { + $('#loading-scopes').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + })).done(function() { + $('#loadingbox').sheet('hide'); + callback(); + }); + } else { // we need to get the client information from the list - - if (this.model.isFetched && - this.options.clientList.isFetched && - this.options.systemScopeList.isFetched) { - + + if (this.model.isFetched && this.options.clientList.isFetched && this.options.systemScopeList.isFetched) { + var client = this.options.clientList.getByClientId(this.model.get('clientId')); this.options.client = client; - - callback(); - return; - } - - $('#loadingbox').sheet('show'); - $('#loading').html( - '' + $.t('whitelist.whitelist') + ' ' + - '' + $.t('common.clients') + ' ' + - '' + $.t('common.scopes') + ' ' - ); - - var _self = this; - - $.when(this.model.fetchIfNeeded({success:function(e) {$('#loading-whitelist').addClass('label-success');}, error: app.errorHandlerView.handleError()}), - this.options.clientList.fetchIfNeeded({success:function(e) {$('#loading-clients').addClass('label-success');}, error: app.errorHandlerView.handleError()}), - this.options.systemScopeList.fetchIfNeeded({success:function(e) {$('#loading-scopes').addClass('label-success');}, error: app.errorHandlerView.handleError()})) - .done(function() { - - var client = _self.options.clientList.getByClientId(_self.model.get('clientId')); - _self.options.client = client; - - $('#loadingbox').sheet('hide'); - callback(); - }); - + + callback(); + return; + } + + $('#loadingbox').sheet('show'); + $('#loading').html('' + $.t('whitelist.whitelist') + ' ' + '' + $.t('common.clients') + ' ' + '' + $.t('common.scopes') + ' '); + + var _self = this; + + $.when(this.model.fetchIfNeeded({ + success: function(e) { + $('#loading-whitelist').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + }), this.options.clientList.fetchIfNeeded({ + success: function(e) { + $('#loading-clients').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + }), this.options.systemScopeList.fetchIfNeeded({ + success: function(e) { + $('#loading-scopes').addClass('label-success'); + }, + error: app.errorHandlerView.handleError() + })).done(function() { + + var client = _self.options.clientList.getByClientId(_self.model.get('clientId')); + _self.options.client = client; + + $('#loadingbox').sheet('hide'); + callback(); + }); + } - - - }, - - events:{ - 'click .btn-save':'saveWhiteList', - 'click .btn-cancel':'cancelWhiteList', - + + events: { + 'click .btn-save': 'saveWhiteList', + 'click .btn-cancel': 'cancelWhiteList', + }, - - saveWhiteList:function (e) { - e.preventDefault(); + + saveWhiteList: function(e) { + e.preventDefault(); $('.control-group').removeClass('error'); - - // sync any leftover collection items - _.each(this.listWidgetViews, function(v) { - v.addItem($.Event('click')); - }); - + + // sync any leftover collection items + _.each(this.listWidgetViews, function(v) { + v.addItem($.Event('click')); + }); + // process allowed scopes - var allowedScopes = this.scopeCollection.pluck("item"); - - this.model.set({clientId: this.options.client.get('clientId')}, {silent: true}); - + var allowedScopes = this.scopeCollection.pluck("item"); + + this.model.set({ + clientId: this.options.client.get('clientId') + }, { + silent: true + }); + var valid = this.model.set({ allowedScopes: allowedScopes }); - - if (valid) { - var _self = this; - this.model.save({}, { - success:function () { - app.whiteListList.add(_self.model); - app.navigate('admin/whitelists', {trigger:true}); - }, - error:app.errorHandlerView.handleError() - }); - } - - return false; - + + if (valid) { + var _self = this; + this.model.save({}, { + success: function() { + app.whiteListList.add(_self.model); + app.navigate('admin/whitelists', { + trigger: true + }); + }, + error: app.errorHandlerView.handleError() + }); + } + + return false; + }, - - cancelWhiteList:function(e) { - e.preventDefault(); - // TODO: figure out where we came from and go back there instead - if (this.model.get('id') == null) { - // if it's a new whitelist entry, go back to the client listing page - app.navigate('admin/clients', {trigger:true}); - } else { - // if we're editing a whitelist, go back to the whitelists page - app.navigate('admin/whitelists', {trigger:true}); - } + + cancelWhiteList: function(e) { + e.preventDefault(); + // TODO: figure out where we came from and go back there instead + if (this.model.get('id') == null) { + // if it's a new whitelist entry, go back to the client listing page + app.navigate('admin/clients', { + trigger: true + }); + } else { + // if we're editing a whitelist, go back to the whitelists page + app.navigate('admin/whitelists', { + trigger: true + }); + } }, - - render:function (eventName) { - - var json = {whiteList: this.model.toJSON(), client: this.options.client.toJSON()}; - + + render: function(eventName) { + + var json = { + whiteList: this.model.toJSON(), + client: this.options.client.toJSON() + }; + this.$el.html(this.template(json)); - + this.listWidgetViews = []; - - var _self = this; - // build and bind scopes - _.each(this.model.get("allowedScopes"), function (scope) { - _self.scopeCollection.add(new Backbone.Model({item:scope})); - }); - - var scopeView = new ListWidgetView({ - placeholder: $.t('whitelist.whitelist-form.scope-placeholder'), - autocomplete: this.options.client.get("scope"), - helpBlockText: $.t('whitelist.whitelist-form.scope-help'), - collection: this.scopeCollection}); - $("#scope .controls",this.el).html(scopeView.render().el); - this.listWidgetViews.push(scopeView); - - $(this.el).i18n(); + + var _self = this; + // build and bind scopes + _.each(this.model.get("allowedScopes"), function(scope) { + _self.scopeCollection.add(new Backbone.Model({ + item: scope + })); + }); + + var scopeView = new ListWidgetView({ + placeholder: $.t('whitelist.whitelist-form.scope-placeholder'), + autocomplete: this.options.client.get("scope"), + helpBlockText: $.t('whitelist.whitelist-form.scope-help'), + collection: this.scopeCollection + }); + $("#scope .controls", this.el).html(scopeView.render().el); + this.listWidgetViews.push(scopeView); + + $(this.el).i18n(); return this; } }); - -ui.routes.push({path: "admin/whitelists", name: "whiteList", callback: - function () { +ui.routes.push({ + path: "admin/whitelists", + name: "whiteList", + callback: function() { if (!isAdmin()) { this.root(); return; } - - this.updateSidebar('admin/whitelists'); - - this.breadCrumbView.collection.reset(); - this.breadCrumbView.collection.add([ - {text:$.t('admin.home'), href:""}, - {text:$.t('whitelist.manage'), href:"manage/#admin/whitelists"} - ]); - - var view = new WhiteListListView({model:this.whiteListList, clientList: this.clientList, systemScopeList: this.systemScopeList}); - - view.load( - function() { - $('#content').html(view.render().el); - view.delegateEvents(); - setPageTitle($.t('whitelist.manage')); - } - ); - - + + this.updateSidebar('admin/whitelists'); + + this.breadCrumbView.collection.reset(); + this.breadCrumbView.collection.add([{ + text: $.t('admin.home'), + href: "" + }, { + text: $.t('whitelist.manage'), + href: "manage/#admin/whitelists" + }]); + + var view = new WhiteListListView({ + model: this.whiteListList, + clientList: this.clientList, + systemScopeList: this.systemScopeList + }); + + view.load(function() { + $('#content').html(view.render().el); + view.delegateEvents(); + setPageTitle($.t('whitelist.manage')); + }); + } }); -ui.routes.push({path: "admin/whitelist/new/:cid", name: "newWhitelist", callback: - function(cid) { - +ui.routes.push({ + path: "admin/whitelist/new/:cid", + name: "newWhitelist", + callback: function(cid) { if (!isAdmin()) { this.root(); return; } - + this.breadCrumbView.collection.reset(); - this.breadCrumbView.collection.add([ - {text:$.t('admin.home'), href:""}, - {text:$.t('whitelist.manage'), href:"manage/#admin/whitelists"}, - {text:$.t('whitelist.new'), href:"manage/#admin/whitelist/new/" + cid} - ]); - - this.updateSidebar('admin/whitelists'); - - var whiteList = new WhiteListModel(); - - var client = this.clientList.get(cid); - if (!client) { - client = new ClientModel({id: cid}); - } - - var view = new WhiteListFormView({model: whiteList, client: client, systemScopeList: this.systemScopeList}); - - view.load( - function() { - - // set the scopes on the model now that everything's loaded - whiteList.set({allowedScopes: client.get('scope')}, {silent: true}); - - $('#content').html(view.render().el); - view.delegateEvents(); - setPageTitle($.t('whitelist.manage')); - } - ); - + this.breadCrumbView.collection.add([{ + text: $.t('admin.home'), + href: "" + }, { + text: $.t('whitelist.manage'), + href: "manage/#admin/whitelists" + }, { + text: $.t('whitelist.new'), + href: "manage/#admin/whitelist/new/" + cid + }]); + + this.updateSidebar('admin/whitelists'); + + var whiteList = new WhiteListModel(); + + var client = this.clientList.get(cid); + if (!client) { + client = new ClientModel({ + id: cid + }); + } + + var view = new WhiteListFormView({ + model: whiteList, + client: client, + systemScopeList: this.systemScopeList + }); + + view.load(function() { + + // set the scopes on the model now that everything's loaded + whiteList.set({ + allowedScopes: client.get('scope') + }, { + silent: true + }); + + $('#content').html(view.render().el); + view.delegateEvents(); + setPageTitle($.t('whitelist.manage')); + }); + } }); - -ui.routes.push({path: "admin/whitelist/:id", name: "editWhitelist", callback: - function(id) { +ui.routes.push({ + path: "admin/whitelist/:id", + name: "editWhitelist", + callback: function(id) { if (!isAdmin()) { this.root(); return; } - + this.breadCrumbView.collection.reset(); - this.breadCrumbView.collection.add([ - {text:$.t('admin.home'), href:""}, - {text:$.t('whitelist.manage'), href:"manage/#admin/whitelists"}, - {text:$.t('whitelist.edit'), href:"manage/#admin/whitelist/" + id} - ]); - - this.updateSidebar('admin/whitelists'); - - var whiteList = this.whiteListList.get(id); - if (!whiteList) { - whiteList = new WhiteListModel({id: id}); - } - - var view = new WhiteListFormView({model: whiteList, clientList: this.clientList, systemScopeList: this.systemScopeList}); - - view.load( - function() { - $('#content').html(view.render().el); - view.delegateEvents(); - setPageTitle($.t('whitelist.manage')); - } - ); - + this.breadCrumbView.collection.add([{ + text: $.t('admin.home'), + href: "" + }, { + text: $.t('whitelist.manage'), + href: "manage/#admin/whitelists" + }, { + text: $.t('whitelist.edit'), + href: "manage/#admin/whitelist/" + id + }]); + + this.updateSidebar('admin/whitelists'); + + var whiteList = this.whiteListList.get(id); + if (!whiteList) { + whiteList = new WhiteListModel({ + id: id + }); + } + + var view = new WhiteListFormView({ + model: whiteList, + clientList: this.clientList, + systemScopeList: this.systemScopeList + }); + + view.load(function() { + $('#content').html(view.render().el); + view.delegateEvents(); + setPageTitle($.t('whitelist.manage')); + }); + } - + }); ui.templates.push('resources/template/whitelist.html'); ui.init.push(function(app) { - app.whiteListList = new WhiteListCollection(); + app.whiteListList = new WhiteListCollection(); }); From 7a225e56c4d788857b4137c115ea3f3064fcd869 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 22 Mar 2017 17:29:37 -0400 Subject: [PATCH 370/465] =?UTF-8?q?don=E2=80=99t=20pack=20wro4j=20into=20.?= =?UTF-8?q?war=20file?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We use it only during compilation, not runtime --- openid-connect-server-webapp/pom.xml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index 528201c049..b8b9d5beea 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -94,15 +94,18 @@ ${project.build.directory}/${project.build.finalName}/js/ ro.isdc.wro.maven.plugin.manager.factory.ConfigurableWroManagerFactory + + + ro.isdc.wro4j + wro4j-extensions + 1.8.0 + +
- - ro.isdc.wro4j - wro4j-extensions - org.mitre openid-connect-server From 7767c7a831d40d0138e8c66c983448721c941b74 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 22 Mar 2017 17:30:08 -0400 Subject: [PATCH 371/465] =?UTF-8?q?add=20=E2=80=9Cif=20not=20exists?= =?UTF-8?q?=E2=80=9D=20to=20all=20indexes=20in=20HSQL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../db/hsql/hsql_database_tables.sql | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql b/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql index 00851a775e..4274e53566 100644 --- a/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql +++ b/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql @@ -383,17 +383,17 @@ CREATE TABLE IF NOT EXISTS device_code_request_parameter ( val VARCHAR(2048) ); -CREATE INDEX at_tv_idx ON access_token(token_value); -CREATE INDEX ts_oi_idx ON token_scope(owner_id); -CREATE INDEX at_exp_idx ON access_token(expiration); -CREATE INDEX rf_ahi_idx ON refresh_token(auth_holder_id); -CREATE INDEX cd_ci_idx ON client_details(client_id); -CREATE INDEX at_ahi_idx ON access_token(auth_holder_id); -CREATE INDEX aha_oi_idx ON authentication_holder_authority(owner_id); -CREATE INDEX ahe_oi_idx ON authentication_holder_extension(owner_id); -CREATE INDEX ahrp_oi_idx ON authentication_holder_request_parameter(owner_id); -CREATE INDEX ahri_oi_idx ON authentication_holder_resource_id(owner_id); -CREATE INDEX ahrt_oi_idx ON authentication_holder_response_type(owner_id); -CREATE INDEX ahs_oi_idx ON authentication_holder_scope(owner_id); -CREATE INDEX ac_ahi_idx ON authorization_code(auth_holder_id); -CREATE INDEX suaa_oi_idx ON saved_user_auth_authority(owner_id); +CREATE INDEX IF NOT EXISTS at_tv_idx ON access_token(token_value); +CREATE INDEX IF NOT EXISTS ts_oi_idx ON token_scope(owner_id); +CREATE INDEX IF NOT EXISTS at_exp_idx ON access_token(expiration); +CREATE INDEX IF NOT EXISTS rf_ahi_idx ON refresh_token(auth_holder_id); +CREATE INDEX IF NOT EXISTS cd_ci_idx ON client_details(client_id); +CREATE INDEX IF NOT EXISTS at_ahi_idx ON access_token(auth_holder_id); +CREATE INDEX IF NOT EXISTS aha_oi_idx ON authentication_holder_authority(owner_id); +CREATE INDEX IF NOT EXISTS ahe_oi_idx ON authentication_holder_extension(owner_id); +CREATE INDEX IF NOT EXISTS ahrp_oi_idx ON authentication_holder_request_parameter(owner_id); +CREATE INDEX IF NOT EXISTS ahri_oi_idx ON authentication_holder_resource_id(owner_id); +CREATE INDEX IF NOT EXISTS ahrt_oi_idx ON authentication_holder_response_type(owner_id); +CREATE INDEX IF NOT EXISTS ahs_oi_idx ON authentication_holder_scope(owner_id); +CREATE INDEX IF NOT EXISTS ac_ahi_idx ON authorization_code(auth_holder_id); +CREATE INDEX IF NOT EXISTS suaa_oi_idx ON saved_user_auth_authority(owner_id); From 050662dd5ceede080f99367d0af707aa63ae2e67 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 24 Mar 2017 12:12:06 -0400 Subject: [PATCH 372/465] updated dependencies --- .../impl/TestSignedAuthRequestUrlBuilder.java | 2 +- .../SymmetricKeyJWTValidatorCacheService.java | 2 +- .../org/mitre/jose/TestJWKSetKeyStore.java | 4 +- ...aultJWTEncryptionAndDecryptionService.java | 8 +- openid-connect-server-webapp/pom.xml | 7 -- pom.xml | 99 +++++++++++-------- uma-server-webapp/pom.xml | 36 +------ 7 files changed, 69 insertions(+), 89 deletions(-) diff --git a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestSignedAuthRequestUrlBuilder.java b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestSignedAuthRequestUrlBuilder.java index 8ba354dc7d..ee5ecd71aa 100644 --- a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestSignedAuthRequestUrlBuilder.java +++ b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestSignedAuthRequestUrlBuilder.java @@ -91,7 +91,7 @@ public class TestSignedAuthRequestUrlBuilder { @Before public void prepare() throws NoSuchAlgorithmException, InvalidKeySpecException { - RSAKey key = new RSAKey(new Base64URL(n), new Base64URL(e), new Base64URL(d), KeyUse.SIGNATURE, null, new Algorithm(alg), kid, null, null, null); + RSAKey key = new RSAKey(new Base64URL(n), new Base64URL(e), new Base64URL(d), KeyUse.SIGNATURE, null, new Algorithm(alg), kid, null, null, null, null); Map keys = Maps.newHashMap(); keys.put("client", key); diff --git a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/SymmetricKeyJWTValidatorCacheService.java b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/SymmetricKeyJWTValidatorCacheService.java index f90a732861..d034ceb6e9 100644 --- a/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/SymmetricKeyJWTValidatorCacheService.java +++ b/openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/SymmetricKeyJWTValidatorCacheService.java @@ -101,7 +101,7 @@ public JWTSigningAndValidationService load(String key) throws Exception { String id = "SYMMETRIC-KEY"; - JWK jwk = new OctetSequenceKey(Base64URL.encode(key), KeyUse.SIGNATURE, null, null, id, null, null, null); + JWK jwk = new OctetSequenceKey(Base64URL.encode(key), KeyUse.SIGNATURE, null, null, id, null, null, null, null); Map keys = ImmutableMap.of(id, jwk); JWTSigningAndValidationService service = new DefaultJWTSigningAndValidationService(keys); diff --git a/openid-connect-common/src/test/java/org/mitre/jose/TestJWKSetKeyStore.java b/openid-connect-common/src/test/java/org/mitre/jose/TestJWKSetKeyStore.java index d894edddd8..c6efada2bf 100644 --- a/openid-connect-common/src/test/java/org/mitre/jose/TestJWKSetKeyStore.java +++ b/openid-connect-common/src/test/java/org/mitre/jose/TestJWKSetKeyStore.java @@ -62,7 +62,7 @@ public class TestJWKSetKeyStore { "qDp0Vqj3kbSCz1XyfCs6_LehBwtxHIyh8Ripy40p24moOAbgxVw3rxT_vl" + "t3UVe4WO3JkJOzlpUf-KTVI2Ptgm-dARxTEtE-id-4OJr0h-K-VFs3VSnd" + "VTIznSxfyrj8ILL6MG_Uv8YAu7VILSB3lOW085-4qE3DzgrTjgyQ"), // d - KeyUse.ENCRYPTION, null, JWEAlgorithm.RSA_OAEP, RSAkid, null, null, null); + KeyUse.ENCRYPTION, null, JWEAlgorithm.RSA_OAEP, RSAkid, null, null, null, null); private String RSAkid_rsa2 = "rsa_2"; private JWK RSAjwk_rsa2 = new RSAKey( @@ -79,7 +79,7 @@ public class TestJWKSetKeyStore { "qDp0Vqj3kbSCz1XyfCs6_LehBwtxHIyh8Ripy40p24moOAbgxVw3rxT_vl" + "t3UVe4WO3JkJOzlpUf-KTVI2Ptgm-dARxTEtE-id-4OJr0h-K-VFs3VSnd" + "VTIznSxfyrj8ILL6MG_Uv8YAu7VILSB3lOW085-4qE3DzgrTjgyQ"), // d - KeyUse.ENCRYPTION, null, JWEAlgorithm.RSA1_5, RSAkid_rsa2, null, null, null); + KeyUse.ENCRYPTION, null, JWEAlgorithm.RSA1_5, RSAkid_rsa2, null, null, null, null); List keys_list = new LinkedList<>(); diff --git a/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java b/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java index 06f399f094..a5c851e9e6 100644 --- a/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java +++ b/openid-connect-common/src/test/java/org/mitre/jwt/encryption/service/impl/TestDefaultJWTEncryptionAndDecryptionService.java @@ -105,7 +105,7 @@ public class TestDefaultJWTEncryptionAndDecryptionService { "qDp0Vqj3kbSCz1XyfCs6_LehBwtxHIyh8Ripy40p24moOAbgxVw3rxT_vl" + "t3UVe4WO3JkJOzlpUf-KTVI2Ptgm-dARxTEtE-id-4OJr0h-K-VFs3VSnd" + "VTIznSxfyrj8ILL6MG_Uv8YAu7VILSB3lOW085-4qE3DzgrTjgyQ"), // d - KeyUse.ENCRYPTION, null, JWEAlgorithm.RSA_OAEP, RSAkid, null, null, null); + KeyUse.ENCRYPTION, null, JWEAlgorithm.RSA_OAEP, RSAkid, null, null, null, null); private String RSAkid_2 = "rsa3210"; private JWK RSAjwk_2 = new RSAKey( @@ -122,12 +122,12 @@ public class TestDefaultJWTEncryptionAndDecryptionService { "qDp0Vqj3kbSCz1XyfCs6_LehBwtxHIyh8Ripy40p24moOAbgxVw3rxT_vl" + "t3UVe4WO3JkJOzlpUf-KTVI2Ptgm-dARxTEtE-id-4OJr0h-K-VFs3VSnd" + "VTIznSxfyrj8ILL6MG_Uv8YAu7VILSB3lOW085-4qE3DzgrTjgyQ"), // d - KeyUse.ENCRYPTION, null, JWEAlgorithm.RSA1_5, RSAkid_2, null, null, null); + KeyUse.ENCRYPTION, null, JWEAlgorithm.RSA1_5, RSAkid_2, null, null, null, null); private String AESkid = "aes123"; - private JWK AESjwk = new OctetSequenceKey( new Base64URL("GawgguFyGrWKav7AX4VKUg"), + private JWK AESjwk = new OctetSequenceKey(new Base64URL("GawgguFyGrWKav7AX4VKUg"), KeyUse.ENCRYPTION, null, JWEAlgorithm.A128KW, - AESkid, null, null, null); + AESkid, null, null, null, null); private Map keys = new ImmutableMap.Builder() diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index b8b9d5beea..cb3386dabc 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -94,13 +94,6 @@ ${project.build.directory}/${project.build.finalName}/js/ ro.isdc.wro.maven.plugin.manager.factory.ConfigurableWroManagerFactory - - - ro.isdc.wro4j - wro4j-extensions - 1.8.0 - - diff --git a/pom.xml b/pom.xml index a8bbcf5e82..d4901e67b9 100644 --- a/pom.xml +++ b/pom.xml @@ -70,7 +70,7 @@ 1.8 - 1.7.21 + 1.7.25 A reference implementation of OpenID Connect (http://openid.net/connect/), OAuth 2.0, and UMA built on top of Java, Spring, and Spring Security. The project contains a fully functioning server, client, and utility library. https://github.com/mitreid-connect @@ -80,48 +80,43 @@ org.apache.maven.plugins maven-jar-plugin - 2.4 + 3.0.2 org.apache.maven.plugins maven-war-plugin - 2.6 - - - org.apache.maven.plugins - maven-archiver - 2.5 + 3.0.0 org.apache.maven.plugins maven-javadoc-plugin - 2.9 + 2.10.4 org.apache.maven.plugins maven-deploy-plugin - 2.7 + 2.8.2 org.apache.maven.plugins maven-source-plugin - 2.2 + 3.0.1 org.apache.maven.plugins maven-compiler-plugin - 2.5.1 + 3.6.1 org.eclipse.jetty jetty-maven-plugin - 9.3.3.v20150827 + 9.4.3.v20170317 true org.apache.maven.plugins maven-enforcer-plugin - 1.3 + 1.4.1 org.appfuse.plugins @@ -131,24 +126,43 @@ org.apache.maven.plugins maven-site-plugin - 3.3 + 3.6 org.apache.maven.plugins maven-project-info-reports-plugin 2.9 + - org.lesscss - lesscss-maven-plugin - 1.7.0.1.1 - - - - compile - - - + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + + org.appfuse.plugins + + + warpath-maven-plugin + + + [3.5.0,) + + + add-classes + + + + + + + + + ro.isdc.wro4j @@ -162,6 +176,13 @@ + + + ro.isdc.wro4j + wro4j-extensions + 1.8.0 + + @@ -336,7 +357,7 @@ org.springframework spring-framework-bom - 4.3.4.RELEASE + 4.3.7.RELEASE pom import @@ -345,26 +366,26 @@ com.fasterxml.jackson.core jackson-databind - 2.3.4 + 2.9.0.pr2 com.fasterxml.jackson.core jackson-annotations - 2.3.4 + 2.9.0.pr2 org.springframework.security spring-security-bom - 4.2.0.RELEASE + 4.2.2.RELEASE pom import org.springframework.security.oauth spring-security-oauth2 - 2.0.12.RELEASE + 2.1.0.RELEASE @@ -390,7 +411,7 @@ mysql mysql-connector-java - 5.1.34 + 6.0.6 org.hsqldb @@ -400,7 +421,7 @@ org.postgresql postgresql - 9.4-1201-jdbc4 + 42.0.0.jre7 com.oracle @@ -420,7 +441,7 @@ com.zaxxer HikariCP - 2.4.1 + 2.6.1 @@ -450,7 +471,7 @@ log4j log4j - 1.2.15 + 1.2.17 javax.mail @@ -476,13 +497,13 @@ junit junit - 4.7 + 4.12 test org.easymock easymock - 2.0 + 3.4 test @@ -543,7 +564,7 @@ com.google.guava guava - 20.0 + 21.0 com.google.code.gson @@ -553,7 +574,7 @@ org.apache.httpcomponents httpclient - 4.5.2 + 4.5.3 commons-logging @@ -564,7 +585,7 @@ com.nimbusds nimbus-jose-jwt - 4.33 + 4.34.2 org.bouncycastle diff --git a/uma-server-webapp/pom.xml b/uma-server-webapp/pom.xml index 81f4705057..0c48f65e8e 100644 --- a/uma-server-webapp/pom.xml +++ b/uma-server-webapp/pom.xml @@ -60,6 +60,7 @@ openid-connect-server-webapp + false @@ -73,41 +74,6 @@ - - - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - - org.appfuse.plugins - - - warpath-maven-plugin - - - [3.5.0,) - - - add-classes - - - - - - - - - - - -
From 2ea5f8fd28ed89efd1584bd9366e30d28b3c0c59 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 24 Mar 2017 12:41:14 -0400 Subject: [PATCH 373/465] =?UTF-8?q?sync=E2=80=99d=20databases=20with=20HSQ?= =?UTF-8?q?L=20schema,=20closes=20#1212?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../db/mysql/mysql_database_tables.sql | 56 +++++++++++++------ .../db/oracle/oracle_database_tables.sql | 24 ++++++++ .../db/psql/psql_database_tables.sql | 54 +++++++++++++----- 3 files changed, 102 insertions(+), 32 deletions(-) diff --git a/openid-connect-server-webapp/src/main/resources/db/mysql/mysql_database_tables.sql b/openid-connect-server-webapp/src/main/resources/db/mysql/mysql_database_tables.sql index 04839343d5..ad876b6f40 100644 --- a/openid-connect-server-webapp/src/main/resources/db/mysql/mysql_database_tables.sql +++ b/openid-connect-server-webapp/src/main/resources/db/mysql/mysql_database_tables.sql @@ -10,7 +10,8 @@ CREATE TABLE IF NOT EXISTS access_token ( refresh_token_id BIGINT, client_id BIGINT, auth_holder_id BIGINT, - approved_site_id BIGINT + approved_site_id BIGINT, + UNIQUE(token_value) ); CREATE TABLE IF NOT EXISTS access_token_permissions ( @@ -130,6 +131,7 @@ CREATE TABLE IF NOT EXISTS client_details ( dynamically_registered BOOLEAN DEFAULT false NOT NULL, allow_introspection BOOLEAN DEFAULT false NOT NULL, id_token_validity_seconds BIGINT DEFAULT 600 NOT NULL, + device_code_validity_seconds BIGINT, client_id VARCHAR(256), client_secret VARCHAR(2048), @@ -169,6 +171,8 @@ CREATE TABLE IF NOT EXISTS client_details ( clear_access_tokens_on_refresh BOOLEAN DEFAULT true NOT NULL, software_statement VARCHAR(4096), + software_id VARCHAR(2048), + software_version VARCHAR(2048), code_challenge_method VARCHAR(256), @@ -235,8 +239,6 @@ CREATE TABLE IF NOT EXISTS system_scope ( icon VARCHAR(256), restricted BOOLEAN DEFAULT false NOT NULL, default_scope BOOLEAN DEFAULT false NOT NULL, - structured BOOLEAN DEFAULT false NOT NULL, - structured_param_description VARCHAR(256), UNIQUE (scope) ); @@ -360,18 +362,38 @@ CREATE TABLE IF NOT EXISTS saved_registered_client ( registered_client VARCHAR(8192) ); +CREATE TABLE IF NOT EXISTS device_code ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + device_code VARCHAR(1024), + user_code VARCHAR(1024), + expiration TIMESTAMP NULL, + client_id VARCHAR(256), + approved BOOLEAN, + auth_holder_id BIGINT +); + +CREATE TABLE IF NOT EXISTS device_code_scope ( + owner_id BIGINT NOT NULL, + scope VARCHAR(256) NOT NULL +); + +CREATE TABLE IF NOT EXISTS device_code_request_parameter ( + owner_id BIGINT, + param VARCHAR(2048), + val VARCHAR(2048) +); -CREATE INDEX at_tv_idx ON access_token(token_value(767)); -CREATE INDEX ts_oi_idx ON token_scope(owner_id); -CREATE INDEX at_exp_idx ON access_token(expiration); -CREATE INDEX rf_ahi_idx ON refresh_token(auth_holder_id); -CREATE INDEX cd_ci_idx ON client_details(client_id); -CREATE INDEX at_ahi_idx ON access_token(auth_holder_id); -CREATE INDEX aha_oi_idx ON authentication_holder_authority(owner_id); -CREATE INDEX ahe_oi_idx ON authentication_holder_extension(owner_id); -CREATE INDEX ahrp_oi_idx ON authentication_holder_request_parameter(owner_id); -CREATE INDEX ahri_oi_idx ON authentication_holder_resource_id(owner_id); -CREATE INDEX ahrt_oi_idx ON authentication_holder_response_type(owner_id); -CREATE INDEX ahs_oi_idx ON authentication_holder_scope(owner_id); -CREATE INDEX ac_ahi_idx ON authorization_code(auth_holder_id); -CREATE INDEX suaa_oi_idx ON saved_user_auth_authority(owner_id); +CREATE INDEX IF NOT EXISTS at_tv_idx ON access_token(token_value(767)); +CREATE INDEX IF NOT EXISTS ts_oi_idx ON token_scope(owner_id); +CREATE INDEX IF NOT EXISTS at_exp_idx ON access_token(expiration); +CREATE INDEX IF NOT EXISTS rf_ahi_idx ON refresh_token(auth_holder_id); +CREATE INDEX IF NOT EXISTS cd_ci_idx ON client_details(client_id); +CREATE INDEX IF NOT EXISTS at_ahi_idx ON access_token(auth_holder_id); +CREATE INDEX IF NOT EXISTS aha_oi_idx ON authentication_holder_authority(owner_id); +CREATE INDEX IF NOT EXISTS ahe_oi_idx ON authentication_holder_extension(owner_id); +CREATE INDEX IF NOT EXISTS ahrp_oi_idx ON authentication_holder_request_parameter(owner_id); +CREATE INDEX IF NOT EXISTS ahri_oi_idx ON authentication_holder_resource_id(owner_id); +CREATE INDEX IF NOT EXISTS ahrt_oi_idx ON authentication_holder_response_type(owner_id); +CREATE INDEX IF NOT EXISTS ahs_oi_idx ON authentication_holder_scope(owner_id); +CREATE INDEX IF NOT EXISTS ac_ahi_idx ON authorization_code(auth_holder_id); +CREATE INDEX IF NOT EXISTS suaa_oi_idx ON saved_user_auth_authority(owner_id); diff --git a/openid-connect-server-webapp/src/main/resources/db/oracle/oracle_database_tables.sql b/openid-connect-server-webapp/src/main/resources/db/oracle/oracle_database_tables.sql index 440a3a08ab..7c48fe0e54 100644 --- a/openid-connect-server-webapp/src/main/resources/db/oracle/oracle_database_tables.sql +++ b/openid-connect-server-webapp/src/main/resources/db/oracle/oracle_database_tables.sql @@ -146,6 +146,7 @@ CREATE TABLE client_details ( client_secret VARCHAR2(2048), access_token_validity_seconds NUMBER(19), refresh_token_validity_seconds NUMBER(19), + device_code_validity_seconds NUMBER(19), application_type VARCHAR2(256), client_name VARCHAR2(256), @@ -179,6 +180,8 @@ CREATE TABLE client_details ( initiate_login_uri VARCHAR2(2048), clear_access_tokens_on_refresh NUMBER(1) DEFAULT 1 NOT NULL, + software_statement VARCHAR(4096), + software_id VARCHAR(2048), software_statement VARCHAR2(4000), code_challenge_method VARCHAR2(256), @@ -395,6 +398,27 @@ CREATE TABLE saved_registered_client ( ); CREATE SEQUENCE saved_registered_client_seq START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE; +CREATE TABLE IF NOT EXISTS device_code ( + id NUMBER(19) NOT NULL PRIMARY KEY, + device_code VARCHAR2(1024), + user_code VARCHAR2(1024), + expiration TIMESTAMP, + client_id VARCHAR2(256), + approved BOOLEAN, + auth_holder_id NUMBER(19) +); + +CREATE TABLE IF NOT EXISTS device_code_scope ( + owner_id NUMBER(19) NOT NULL, + scope VARCHAR2(256) NOT NULL +); + +CREATE TABLE IF NOT EXISTS device_code_request_parameter ( + owner_id NUMBER(19), + param VARCHAR2(2048), + val VARCHAR2(2048) +); + CREATE INDEX at_tv_idx ON access_token(token_value); CREATE INDEX ts_oi_idx ON token_scope(owner_id); CREATE INDEX at_exp_idx ON access_token(expiration); diff --git a/openid-connect-server-webapp/src/main/resources/db/psql/psql_database_tables.sql b/openid-connect-server-webapp/src/main/resources/db/psql/psql_database_tables.sql index 47985f0ad3..d21e95be0b 100644 --- a/openid-connect-server-webapp/src/main/resources/db/psql/psql_database_tables.sql +++ b/openid-connect-server-webapp/src/main/resources/db/psql/psql_database_tables.sql @@ -10,7 +10,8 @@ CREATE TABLE IF NOT EXISTS access_token ( refresh_token_id BIGINT, client_id BIGINT, auth_holder_id BIGINT, - approved_site_id BIGINT + approved_site_id BIGINT, + UNIQUE(token_value) ); CREATE TABLE IF NOT EXISTS access_token_permissions ( @@ -130,6 +131,7 @@ CREATE TABLE IF NOT EXISTS client_details ( dynamically_registered BOOLEAN DEFAULT false NOT NULL, allow_introspection BOOLEAN DEFAULT false NOT NULL, id_token_validity_seconds BIGINT DEFAULT 600 NOT NULL, + device_code_validity_seconds BIGINT, client_id VARCHAR(256), client_secret VARCHAR(2048), @@ -169,6 +171,8 @@ CREATE TABLE IF NOT EXISTS client_details ( clear_access_tokens_on_refresh BOOLEAN DEFAULT true NOT NULL, software_statement VARCHAR(4096), + software_id VARCHAR(2048), + software_version VARCHAR(2048), code_challenge_method VARCHAR(256), @@ -360,18 +364,38 @@ CREATE TABLE IF NOT EXISTS saved_registered_client ( registered_client VARCHAR(8192) ); +CREATE TABLE IF NOT EXISTS device_code ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + device_code VARCHAR(1024), + user_code VARCHAR(1024), + expiration TIMESTAMP NULL, + client_id VARCHAR(256), + approved BOOLEAN, + auth_holder_id BIGINT +); + +CREATE TABLE IF NOT EXISTS device_code_scope ( + owner_id BIGINT NOT NULL, + scope VARCHAR(256) NOT NULL +); + +CREATE TABLE IF NOT EXISTS device_code_request_parameter ( + owner_id BIGINT, + param VARCHAR(2048), + val VARCHAR(2048) +); -CREATE INDEX at_tv_idx ON access_token(token_value); -CREATE INDEX ts_oi_idx ON token_scope(owner_id); -CREATE INDEX at_exp_idx ON access_token(expiration); -CREATE INDEX rf_ahi_idx ON refresh_token(auth_holder_id); -CREATE INDEX cd_ci_idx ON client_details(client_id); -CREATE INDEX at_ahi_idx ON access_token(auth_holder_id); -CREATE INDEX aha_oi_idx ON authentication_holder_authority(owner_id); -CREATE INDEX ahe_oi_idx ON authentication_holder_extension(owner_id); -CREATE INDEX ahrp_oi_idx ON authentication_holder_request_parameter(owner_id); -CREATE INDEX ahri_oi_idx ON authentication_holder_resource_id(owner_id); -CREATE INDEX ahrt_oi_idx ON authentication_holder_response_type(owner_id); -CREATE INDEX ahs_oi_idx ON authentication_holder_scope(owner_id); -CREATE INDEX ac_ahi_idx ON authorization_code(auth_holder_id); -CREATE INDEX suaa_oi_idx ON saved_user_auth_authority(owner_id); +CREATE INDEX IF NOT EXISTS at_tv_idx ON access_token(token_value); +CREATE INDEX IF NOT EXISTS ts_oi_idx ON token_scope(owner_id); +CREATE INDEX IF NOT EXISTS at_exp_idx ON access_token(expiration); +CREATE INDEX IF NOT EXISTS rf_ahi_idx ON refresh_token(auth_holder_id); +CREATE INDEX IF NOT EXISTS cd_ci_idx ON client_details(client_id); +CREATE INDEX IF NOT EXISTS at_ahi_idx ON access_token(auth_holder_id); +CREATE INDEX IF NOT EXISTS aha_oi_idx ON authentication_holder_authority(owner_id); +CREATE INDEX IF NOT EXISTS ahe_oi_idx ON authentication_holder_extension(owner_id); +CREATE INDEX IF NOT EXISTS ahrp_oi_idx ON authentication_holder_request_parameter(owner_id); +CREATE INDEX IF NOT EXISTS ahri_oi_idx ON authentication_holder_resource_id(owner_id); +CREATE INDEX IF NOT EXISTS ahrt_oi_idx ON authentication_holder_response_type(owner_id); +CREATE INDEX IF NOT EXISTS ahs_oi_idx ON authentication_holder_scope(owner_id); +CREATE INDEX IF NOT EXISTS ac_ahi_idx ON authorization_code(auth_holder_id); +CREATE INDEX IF NOT EXISTS suaa_oi_idx ON saved_user_auth_authority(owner_id); From 1d7fba5d6e23850da48f40311c48c19c01e3bf60 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 24 Mar 2017 12:44:49 -0400 Subject: [PATCH 374/465] added cascade to address object, closes #1209 --- .../java/org/mitre/openid/connect/model/DefaultUserInfo.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultUserInfo.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultUserInfo.java index 5fe70b5c07..32efea98bb 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultUserInfo.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultUserInfo.java @@ -21,6 +21,7 @@ import java.io.ObjectOutputStream; import javax.persistence.Basic; +import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Convert; import javax.persistence.Entity; @@ -369,7 +370,7 @@ public void setPhoneNumberVerified(Boolean phoneNumberVerified) { * @see org.mitre.openid.connect.model.UserInfo#getAddress() */ @Override - @OneToOne(targetEntity = DefaultAddress.class) + @OneToOne(targetEntity = DefaultAddress.class, cascade = CascadeType.ALL) @JoinColumn(name="address_id") public Address getAddress() { return address; From 835a32662768837e67415220d4dd14445c669642 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 27 Mar 2017 14:39:40 -0500 Subject: [PATCH 375/465] allow polling of device codes, fixed UI for device code input --- .../oauth2/service/DeviceCodeService.java | 10 +++++- .../webapp/WEB-INF/views/approveDevice.jsp | 9 ++--- .../webapp/WEB-INF/views/requestUserCode.jsp | 2 +- .../impl/DefaultDeviceCodeService.java | 34 ++++++++++++++----- .../oauth2/token/DeviceTokenGranter.java | 8 +++-- 5 files changed, 47 insertions(+), 16 deletions(-) diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java b/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java index a0067b909a..35968b9e07 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java @@ -48,8 +48,16 @@ public interface DeviceCodeService { * @param client * @return */ - public DeviceCode consumeDeviceCode(String deviceCode, ClientDetails client); + public DeviceCode findDeviceCode(String deviceCode, ClientDetails client); + + /** + * + * @param deviceCode + * @param client + */ + public void clearDeviceCode(String deviceCode, ClientDetails client); + /** * @param deviceCode * @param userCode diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/approveDevice.jsp b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/approveDevice.jsp index bcc6882ca2..c49e1e8741 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/approveDevice.jsp +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/approveDevice.jsp @@ -37,7 +37,7 @@ + action="${pageContext.request.contextPath.endsWith('/') ? pageContext.request.contextPath : pageContext.request.contextPath.concat('/') }device/approve" method="post">
@@ -163,8 +163,9 @@
+
    - +
  • @@ -199,9 +200,9 @@ - +
  • - +
diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/requestUserCode.jsp b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/requestUserCode.jsp index c629d0b9f0..69a6ed3016 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/requestUserCode.jsp +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/requestUserCode.jsp @@ -39,7 +39,7 @@ - +
diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java index 8020de7a63..1d8f6282e8 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java @@ -90,22 +90,26 @@ public DeviceCode approveDeviceCode(DeviceCode dc, OAuth2Authentication auth) { * @see org.mitre.oauth2.service.DeviceCodeService#consumeDeviceCode(java.lang.String, org.springframework.security.oauth2.provider.ClientDetails) */ @Override - public DeviceCode consumeDeviceCode(String deviceCode, ClientDetails client) { + public DeviceCode findDeviceCode(String deviceCode, ClientDetails client) { DeviceCode found = repository.getByDeviceCode(deviceCode); - // make sure it's not used twice - repository.remove(found); - - if (found.getClientId().equals(client.getClientId())) { - // make sure the client matches, if so, we're good - return found; + if (found != null) { + if (found.getClientId().equals(client.getClientId())) { + // make sure the client matches, if so, we're good + return found; + } else { + // if the clients don't match, pretend the code wasn't found + return null; + } } else { - // if the clients don't match, pretend the code wasn't found + // didn't find the code, return null return null; } } + + /* (non-Javadoc) * @see org.mitre.oauth2.service.DeviceCodeService#clearExpiredDeviceCodes() */ @@ -126,4 +130,18 @@ protected void doOperation(DeviceCode item) { }.execute(); } + /* (non-Javadoc) + * @see org.mitre.oauth2.service.DeviceCodeService#clearDeviceCode(java.lang.String, org.springframework.security.oauth2.provider.ClientDetails) + */ + @Override + public void clearDeviceCode(String deviceCode, ClientDetails client) { + DeviceCode found = findDeviceCode(deviceCode, client); + + if (found != null) { + // make sure it's not used twice + repository.remove(found); + } + + } + } diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/token/DeviceTokenGranter.java b/openid-connect-server/src/main/java/org/mitre/oauth2/token/DeviceTokenGranter.java index c9a6c24310..34fde5410e 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/token/DeviceTokenGranter.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/token/DeviceTokenGranter.java @@ -70,13 +70,15 @@ protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, Tok String deviceCode = tokenRequest.getRequestParameters().get("device_code"); // look up the device code and consume it - DeviceCode dc = deviceCodeService.consumeDeviceCode(deviceCode, client); + DeviceCode dc = deviceCodeService.findDeviceCode(deviceCode, client); if (dc != null) { // make sure the code hasn't expired yet if (dc.getExpiration() != null && dc.getExpiration().before(new Date())) { - // TODO: return an error + + deviceCodeService.clearDeviceCode(deviceCode, client); + throw new DeviceCodeExpiredException("Device code has expired " + deviceCode); } else if (!dc.isApproved()) { @@ -90,6 +92,8 @@ protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, Tok OAuth2Authentication auth = new OAuth2Authentication(getRequestFactory().createOAuth2Request(client, tokenRequest), dc.getAuthenticationHolder().getUserAuth()); + deviceCodeService.clearDeviceCode(deviceCode, client); + return auth; } } else { From bf49cd193d31f91c4ca2439d889856f187cc98c6 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Thu, 6 Apr 2017 14:07:39 -0400 Subject: [PATCH 376/465] removed incompatible constraints on mysql files --- .../db/mysql/mysql_database_tables.sql | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/openid-connect-server-webapp/src/main/resources/db/mysql/mysql_database_tables.sql b/openid-connect-server-webapp/src/main/resources/db/mysql/mysql_database_tables.sql index ad876b6f40..2f316be6e3 100644 --- a/openid-connect-server-webapp/src/main/resources/db/mysql/mysql_database_tables.sql +++ b/openid-connect-server-webapp/src/main/resources/db/mysql/mysql_database_tables.sql @@ -10,8 +10,7 @@ CREATE TABLE IF NOT EXISTS access_token ( refresh_token_id BIGINT, client_id BIGINT, auth_holder_id BIGINT, - approved_site_id BIGINT, - UNIQUE(token_value) + approved_site_id BIGINT ); CREATE TABLE IF NOT EXISTS access_token_permissions ( @@ -383,17 +382,17 @@ CREATE TABLE IF NOT EXISTS device_code_request_parameter ( val VARCHAR(2048) ); -CREATE INDEX IF NOT EXISTS at_tv_idx ON access_token(token_value(767)); -CREATE INDEX IF NOT EXISTS ts_oi_idx ON token_scope(owner_id); -CREATE INDEX IF NOT EXISTS at_exp_idx ON access_token(expiration); -CREATE INDEX IF NOT EXISTS rf_ahi_idx ON refresh_token(auth_holder_id); -CREATE INDEX IF NOT EXISTS cd_ci_idx ON client_details(client_id); -CREATE INDEX IF NOT EXISTS at_ahi_idx ON access_token(auth_holder_id); -CREATE INDEX IF NOT EXISTS aha_oi_idx ON authentication_holder_authority(owner_id); -CREATE INDEX IF NOT EXISTS ahe_oi_idx ON authentication_holder_extension(owner_id); -CREATE INDEX IF NOT EXISTS ahrp_oi_idx ON authentication_holder_request_parameter(owner_id); -CREATE INDEX IF NOT EXISTS ahri_oi_idx ON authentication_holder_resource_id(owner_id); -CREATE INDEX IF NOT EXISTS ahrt_oi_idx ON authentication_holder_response_type(owner_id); -CREATE INDEX IF NOT EXISTS ahs_oi_idx ON authentication_holder_scope(owner_id); -CREATE INDEX IF NOT EXISTS ac_ahi_idx ON authorization_code(auth_holder_id); -CREATE INDEX IF NOT EXISTS suaa_oi_idx ON saved_user_auth_authority(owner_id); +CREATE INDEX at_tv_idx ON access_token(token_value(767)); +CREATE INDEX ts_oi_idx ON token_scope(owner_id); +CREATE INDEX at_exp_idx ON access_token(expiration); +CREATE INDEX rf_ahi_idx ON refresh_token(auth_holder_id); +CREATE INDEX cd_ci_idx ON client_details(client_id); +CREATE INDEX at_ahi_idx ON access_token(auth_holder_id); +CREATE INDEX aha_oi_idx ON authentication_holder_authority(owner_id); +CREATE INDEX ahe_oi_idx ON authentication_holder_extension(owner_id); +CREATE INDEX ahrp_oi_idx ON authentication_holder_request_parameter(owner_id); +CREATE INDEX ahri_oi_idx ON authentication_holder_resource_id(owner_id); +CREATE INDEX ahrt_oi_idx ON authentication_holder_response_type(owner_id); +CREATE INDEX ahs_oi_idx ON authentication_holder_scope(owner_id); +CREATE INDEX ac_ahi_idx ON authorization_code(auth_holder_id); +CREATE INDEX suaa_oi_idx ON saved_user_auth_authority(owner_id); From f43ff5368374250479bcb11e7b3dd480c2dc1ca5 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Thu, 6 Apr 2017 14:12:27 -0400 Subject: [PATCH 377/465] Extracted database indexes to separate files --- .../resources/db/hsql/hsql_database_index.sql | 18 ++++++++++++++++++ .../resources/db/hsql/hsql_database_tables.sql | 15 --------------- .../db/mysql/mysql_database_index.sql | 18 ++++++++++++++++++ .../db/mysql/mysql_database_tables.sql | 15 --------------- .../db/oracle/oracle_database_index.sql | 17 +++++++++++++++++ .../db/oracle/oracle_database_tables.sql | 14 -------------- .../resources/db/psql/psql_database_index.sql | 18 ++++++++++++++++++ .../resources/db/psql/psql_database_tables.sql | 15 --------------- 8 files changed, 71 insertions(+), 59 deletions(-) create mode 100644 openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_index.sql create mode 100644 openid-connect-server-webapp/src/main/resources/db/mysql/mysql_database_index.sql create mode 100644 openid-connect-server-webapp/src/main/resources/db/oracle/oracle_database_index.sql create mode 100644 openid-connect-server-webapp/src/main/resources/db/psql/psql_database_index.sql diff --git a/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_index.sql b/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_index.sql new file mode 100644 index 0000000000..4f61d534f1 --- /dev/null +++ b/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_index.sql @@ -0,0 +1,18 @@ +-- +-- Indexes for HSQLDB +-- + +CREATE INDEX IF NOT EXISTS at_tv_idx ON access_token(token_value); +CREATE INDEX IF NOT EXISTS ts_oi_idx ON token_scope(owner_id); +CREATE INDEX IF NOT EXISTS at_exp_idx ON access_token(expiration); +CREATE INDEX IF NOT EXISTS rf_ahi_idx ON refresh_token(auth_holder_id); +CREATE INDEX IF NOT EXISTS cd_ci_idx ON client_details(client_id); +CREATE INDEX IF NOT EXISTS at_ahi_idx ON access_token(auth_holder_id); +CREATE INDEX IF NOT EXISTS aha_oi_idx ON authentication_holder_authority(owner_id); +CREATE INDEX IF NOT EXISTS ahe_oi_idx ON authentication_holder_extension(owner_id); +CREATE INDEX IF NOT EXISTS ahrp_oi_idx ON authentication_holder_request_parameter(owner_id); +CREATE INDEX IF NOT EXISTS ahri_oi_idx ON authentication_holder_resource_id(owner_id); +CREATE INDEX IF NOT EXISTS ahrt_oi_idx ON authentication_holder_response_type(owner_id); +CREATE INDEX IF NOT EXISTS ahs_oi_idx ON authentication_holder_scope(owner_id); +CREATE INDEX IF NOT EXISTS ac_ahi_idx ON authorization_code(auth_holder_id); +CREATE INDEX IF NOT EXISTS suaa_oi_idx ON saved_user_auth_authority(owner_id); diff --git a/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql b/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql index 4274e53566..2a01756298 100644 --- a/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql +++ b/openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql @@ -382,18 +382,3 @@ CREATE TABLE IF NOT EXISTS device_code_request_parameter ( param VARCHAR(2048), val VARCHAR(2048) ); - -CREATE INDEX IF NOT EXISTS at_tv_idx ON access_token(token_value); -CREATE INDEX IF NOT EXISTS ts_oi_idx ON token_scope(owner_id); -CREATE INDEX IF NOT EXISTS at_exp_idx ON access_token(expiration); -CREATE INDEX IF NOT EXISTS rf_ahi_idx ON refresh_token(auth_holder_id); -CREATE INDEX IF NOT EXISTS cd_ci_idx ON client_details(client_id); -CREATE INDEX IF NOT EXISTS at_ahi_idx ON access_token(auth_holder_id); -CREATE INDEX IF NOT EXISTS aha_oi_idx ON authentication_holder_authority(owner_id); -CREATE INDEX IF NOT EXISTS ahe_oi_idx ON authentication_holder_extension(owner_id); -CREATE INDEX IF NOT EXISTS ahrp_oi_idx ON authentication_holder_request_parameter(owner_id); -CREATE INDEX IF NOT EXISTS ahri_oi_idx ON authentication_holder_resource_id(owner_id); -CREATE INDEX IF NOT EXISTS ahrt_oi_idx ON authentication_holder_response_type(owner_id); -CREATE INDEX IF NOT EXISTS ahs_oi_idx ON authentication_holder_scope(owner_id); -CREATE INDEX IF NOT EXISTS ac_ahi_idx ON authorization_code(auth_holder_id); -CREATE INDEX IF NOT EXISTS suaa_oi_idx ON saved_user_auth_authority(owner_id); diff --git a/openid-connect-server-webapp/src/main/resources/db/mysql/mysql_database_index.sql b/openid-connect-server-webapp/src/main/resources/db/mysql/mysql_database_index.sql new file mode 100644 index 0000000000..bbd5236e3d --- /dev/null +++ b/openid-connect-server-webapp/src/main/resources/db/mysql/mysql_database_index.sql @@ -0,0 +1,18 @@ +-- +-- Indexes for MySQL +-- + +CREATE INDEX at_tv_idx ON access_token(token_value(767)); +CREATE INDEX ts_oi_idx ON token_scope(owner_id); +CREATE INDEX at_exp_idx ON access_token(expiration); +CREATE INDEX rf_ahi_idx ON refresh_token(auth_holder_id); +CREATE INDEX cd_ci_idx ON client_details(client_id); +CREATE INDEX at_ahi_idx ON access_token(auth_holder_id); +CREATE INDEX aha_oi_idx ON authentication_holder_authority(owner_id); +CREATE INDEX ahe_oi_idx ON authentication_holder_extension(owner_id); +CREATE INDEX ahrp_oi_idx ON authentication_holder_request_parameter(owner_id); +CREATE INDEX ahri_oi_idx ON authentication_holder_resource_id(owner_id); +CREATE INDEX ahrt_oi_idx ON authentication_holder_response_type(owner_id); +CREATE INDEX ahs_oi_idx ON authentication_holder_scope(owner_id); +CREATE INDEX ac_ahi_idx ON authorization_code(auth_holder_id); +CREATE INDEX suaa_oi_idx ON saved_user_auth_authority(owner_id); diff --git a/openid-connect-server-webapp/src/main/resources/db/mysql/mysql_database_tables.sql b/openid-connect-server-webapp/src/main/resources/db/mysql/mysql_database_tables.sql index 2f316be6e3..7e00cc8762 100644 --- a/openid-connect-server-webapp/src/main/resources/db/mysql/mysql_database_tables.sql +++ b/openid-connect-server-webapp/src/main/resources/db/mysql/mysql_database_tables.sql @@ -381,18 +381,3 @@ CREATE TABLE IF NOT EXISTS device_code_request_parameter ( param VARCHAR(2048), val VARCHAR(2048) ); - -CREATE INDEX at_tv_idx ON access_token(token_value(767)); -CREATE INDEX ts_oi_idx ON token_scope(owner_id); -CREATE INDEX at_exp_idx ON access_token(expiration); -CREATE INDEX rf_ahi_idx ON refresh_token(auth_holder_id); -CREATE INDEX cd_ci_idx ON client_details(client_id); -CREATE INDEX at_ahi_idx ON access_token(auth_holder_id); -CREATE INDEX aha_oi_idx ON authentication_holder_authority(owner_id); -CREATE INDEX ahe_oi_idx ON authentication_holder_extension(owner_id); -CREATE INDEX ahrp_oi_idx ON authentication_holder_request_parameter(owner_id); -CREATE INDEX ahri_oi_idx ON authentication_holder_resource_id(owner_id); -CREATE INDEX ahrt_oi_idx ON authentication_holder_response_type(owner_id); -CREATE INDEX ahs_oi_idx ON authentication_holder_scope(owner_id); -CREATE INDEX ac_ahi_idx ON authorization_code(auth_holder_id); -CREATE INDEX suaa_oi_idx ON saved_user_auth_authority(owner_id); diff --git a/openid-connect-server-webapp/src/main/resources/db/oracle/oracle_database_index.sql b/openid-connect-server-webapp/src/main/resources/db/oracle/oracle_database_index.sql new file mode 100644 index 0000000000..135d8819cb --- /dev/null +++ b/openid-connect-server-webapp/src/main/resources/db/oracle/oracle_database_index.sql @@ -0,0 +1,17 @@ +-- +-- Indexes for Oracle +-- + +CREATE INDEX at_tv_idx ON access_token(token_value); +CREATE INDEX ts_oi_idx ON token_scope(owner_id); +CREATE INDEX at_exp_idx ON access_token(expiration); +CREATE INDEX rf_ahi_idx ON refresh_token(auth_holder_id); +CREATE INDEX at_ahi_idx ON access_token(auth_holder_id); +CREATE INDEX aha_oi_idx ON authentication_holder_authority(owner_id); +CREATE INDEX ahe_oi_idx ON authentication_holder_extension(owner_id); +CREATE INDEX ahrp_oi_idx ON authentication_holder_request_parameter(owner_id); +CREATE INDEX ahri_oi_idx ON authentication_holder_resource_id(owner_id); +CREATE INDEX ahrt_oi_idx ON authentication_holder_response_type(owner_id); +CREATE INDEX ahs_oi_idx ON authentication_holder_scope(owner_id); +CREATE INDEX ac_ahi_idx ON authorization_code(auth_holder_id); +CREATE INDEX suaa_oi_idx ON saved_user_auth_authority(owner_id); diff --git a/openid-connect-server-webapp/src/main/resources/db/oracle/oracle_database_tables.sql b/openid-connect-server-webapp/src/main/resources/db/oracle/oracle_database_tables.sql index 7c48fe0e54..5f88b689bf 100644 --- a/openid-connect-server-webapp/src/main/resources/db/oracle/oracle_database_tables.sql +++ b/openid-connect-server-webapp/src/main/resources/db/oracle/oracle_database_tables.sql @@ -418,17 +418,3 @@ CREATE TABLE IF NOT EXISTS device_code_request_parameter ( param VARCHAR2(2048), val VARCHAR2(2048) ); - -CREATE INDEX at_tv_idx ON access_token(token_value); -CREATE INDEX ts_oi_idx ON token_scope(owner_id); -CREATE INDEX at_exp_idx ON access_token(expiration); -CREATE INDEX rf_ahi_idx ON refresh_token(auth_holder_id); -CREATE INDEX at_ahi_idx ON access_token(auth_holder_id); -CREATE INDEX aha_oi_idx ON authentication_holder_authority(owner_id); -CREATE INDEX ahe_oi_idx ON authentication_holder_extension(owner_id); -CREATE INDEX ahrp_oi_idx ON authentication_holder_request_parameter(owner_id); -CREATE INDEX ahri_oi_idx ON authentication_holder_resource_id(owner_id); -CREATE INDEX ahrt_oi_idx ON authentication_holder_response_type(owner_id); -CREATE INDEX ahs_oi_idx ON authentication_holder_scope(owner_id); -CREATE INDEX ac_ahi_idx ON authorization_code(auth_holder_id); -CREATE INDEX suaa_oi_idx ON saved_user_auth_authority(owner_id); diff --git a/openid-connect-server-webapp/src/main/resources/db/psql/psql_database_index.sql b/openid-connect-server-webapp/src/main/resources/db/psql/psql_database_index.sql new file mode 100644 index 0000000000..2eabf4f57a --- /dev/null +++ b/openid-connect-server-webapp/src/main/resources/db/psql/psql_database_index.sql @@ -0,0 +1,18 @@ +-- +-- Indexes for PostgreSQL +-- + +CREATE INDEX IF NOT EXISTS at_tv_idx ON access_token(token_value); +CREATE INDEX IF NOT EXISTS ts_oi_idx ON token_scope(owner_id); +CREATE INDEX IF NOT EXISTS at_exp_idx ON access_token(expiration); +CREATE INDEX IF NOT EXISTS rf_ahi_idx ON refresh_token(auth_holder_id); +CREATE INDEX IF NOT EXISTS cd_ci_idx ON client_details(client_id); +CREATE INDEX IF NOT EXISTS at_ahi_idx ON access_token(auth_holder_id); +CREATE INDEX IF NOT EXISTS aha_oi_idx ON authentication_holder_authority(owner_id); +CREATE INDEX IF NOT EXISTS ahe_oi_idx ON authentication_holder_extension(owner_id); +CREATE INDEX IF NOT EXISTS ahrp_oi_idx ON authentication_holder_request_parameter(owner_id); +CREATE INDEX IF NOT EXISTS ahri_oi_idx ON authentication_holder_resource_id(owner_id); +CREATE INDEX IF NOT EXISTS ahrt_oi_idx ON authentication_holder_response_type(owner_id); +CREATE INDEX IF NOT EXISTS ahs_oi_idx ON authentication_holder_scope(owner_id); +CREATE INDEX IF NOT EXISTS ac_ahi_idx ON authorization_code(auth_holder_id); +CREATE INDEX IF NOT EXISTS suaa_oi_idx ON saved_user_auth_authority(owner_id); diff --git a/openid-connect-server-webapp/src/main/resources/db/psql/psql_database_tables.sql b/openid-connect-server-webapp/src/main/resources/db/psql/psql_database_tables.sql index d21e95be0b..d43016a3cd 100644 --- a/openid-connect-server-webapp/src/main/resources/db/psql/psql_database_tables.sql +++ b/openid-connect-server-webapp/src/main/resources/db/psql/psql_database_tables.sql @@ -384,18 +384,3 @@ CREATE TABLE IF NOT EXISTS device_code_request_parameter ( param VARCHAR(2048), val VARCHAR(2048) ); - -CREATE INDEX IF NOT EXISTS at_tv_idx ON access_token(token_value); -CREATE INDEX IF NOT EXISTS ts_oi_idx ON token_scope(owner_id); -CREATE INDEX IF NOT EXISTS at_exp_idx ON access_token(expiration); -CREATE INDEX IF NOT EXISTS rf_ahi_idx ON refresh_token(auth_holder_id); -CREATE INDEX IF NOT EXISTS cd_ci_idx ON client_details(client_id); -CREATE INDEX IF NOT EXISTS at_ahi_idx ON access_token(auth_holder_id); -CREATE INDEX IF NOT EXISTS aha_oi_idx ON authentication_holder_authority(owner_id); -CREATE INDEX IF NOT EXISTS ahe_oi_idx ON authentication_holder_extension(owner_id); -CREATE INDEX IF NOT EXISTS ahrp_oi_idx ON authentication_holder_request_parameter(owner_id); -CREATE INDEX IF NOT EXISTS ahri_oi_idx ON authentication_holder_resource_id(owner_id); -CREATE INDEX IF NOT EXISTS ahrt_oi_idx ON authentication_holder_response_type(owner_id); -CREATE INDEX IF NOT EXISTS ahs_oi_idx ON authentication_holder_scope(owner_id); -CREATE INDEX IF NOT EXISTS ac_ahi_idx ON authorization_code(auth_holder_id); -CREATE INDEX IF NOT EXISTS suaa_oi_idx ON saved_user_auth_authority(owner_id); From 2aecedfb3d273552e15d41b702ddc87e1b168025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonard=20Br=C3=BCnings?= Date: Tue, 4 Apr 2017 15:27:22 +0200 Subject: [PATCH 378/465] Replace cobertura with jacoco to generate code-coverage for codecov.io Change-Id: I031144c375d73aaa39d0a6111d37223ad6e4d655 --- pom.xml | 60 +++++++++++++++++++++------------------------------------ 1 file changed, 22 insertions(+), 38 deletions(-) diff --git a/pom.xml b/pom.xml index d4901e67b9..157847c978 100644 --- a/pom.xml +++ b/pom.xml @@ -2,13 +2,13 @@ - - - - - - - - - - - @@ -512,14 +509,6 @@ 1.9.5 test - - org.codehaus.mojo - cobertura-maven-plugin - 2.7 - test - maven-plugin - - org.mitre @@ -650,11 +639,6 @@ javax.servlet.jsp jsp-api - - org.codehaus.mojo - cobertura-maven-plugin - maven-plugin - From 9d1a50d17ed186bf0d2b3aad6493a173cc8981fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonard=20Br=C3=BCnings?= Date: Tue, 4 Apr 2017 16:09:34 +0200 Subject: [PATCH 379/465] Add codecov badge Change-Id: I04f56036af6bd2ac663843c2c10e8c0cebfb05d3 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f0160151a9..ade8050989 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # MITREid Connect --- -[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.mitre/openid-connect-parent/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.mitre/openid-connect-parent) [![Travis CI](https://travis-ci.org/mitreid-connect/OpenID-Connect-Java-Spring-Server.svg?branch=master)](https://travis-ci.org/mitreid-connect/OpenID-Connect-Java-Spring-Server) +[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.mitre/openid-connect-parent/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.mitre/openid-connect-parent) [![Travis CI](https://travis-ci.org/mitreid-connect/OpenID-Connect-Java-Spring-Server.svg?branch=master)](https://travis-ci.org/mitreid-connect/OpenID-Connect-Java-Spring-Server) [![Codecov](https://codecov.io/github/mitreid-connect/OpenID-Connect-Java-Spring-Server/coverage.svg?branch=master)](https://codecov.io/github/mitreid-connect/OpenID-Connect-Java-Spring-Server) This project contains a certified OpenID Connect reference implementation in Java on the Spring platform, including a functioning [server library](openid-connect-server), [deployable server package](openid-connect-server-webapp), [client (RP) library](openid-connect-client), and general [utility libraries](openid-connect-common). The server can be used as an OpenID Connect Identity Provider as well as a general-purpose OAuth 2.0 Authorization Server. From 6216659cd6584e6589c66f687d4f378f7dfdd411 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 7 Apr 2017 14:58:11 -0400 Subject: [PATCH 380/465] manage reporting plugin versions, added jacoco coverage to reporting --- pom.xml | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 157847c978..45f533ac69 100644 --- a/pom.xml +++ b/pom.xml @@ -92,6 +92,16 @@ maven-javadoc-plugin 2.10.4 + + org.jacoco + jacoco-maven-plugin + 0.7.9 + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.10 + org.apache.maven.plugins maven-deploy-plugin @@ -253,7 +263,6 @@ org.jacoco jacoco-maven-plugin - 0.7.9 @@ -277,7 +286,6 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 2.4 false false @@ -304,7 +312,6 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.9 true true @@ -319,7 +326,6 @@ org.apache.maven.plugins maven-checkstyle-plugin - 2.10 checkstyle.xml @@ -334,6 +340,10 @@ + + org.jacoco + jacoco-maven-plugin + From 903168a94917487c6da53103051f5a64115caa0c Mon Sep 17 00:00:00 2001 From: Mark Janssen Date: Wed, 22 Mar 2017 22:15:02 +0100 Subject: [PATCH 381/465] Decrease log level of trailing slash warning Having an issuer without trailing slash configured is just fine, so there is no reason to log a warning for this every time the discovery endpoint is called. --- .../main/java/org/mitre/discovery/web/DiscoveryEndpoint.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java b/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java index 0c2df3b060..ada2a15c5e 100644 --- a/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java @@ -287,7 +287,7 @@ OPTIONAL. JSON array containing a list of the JWS signing algorithms (alg values String baseUrl = config.getIssuer(); if (!baseUrl.endsWith("/")) { - logger.warn("Configured issuer doesn't end in /, adding for discovery: " + baseUrl); + logger.debug("Configured issuer doesn't end in /, adding for discovery: {}", baseUrl); baseUrl = baseUrl.concat("/"); } From 52829d4adbd90b2dc624be1fd0a0bd58d20bf3da Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 7 Apr 2017 17:02:50 -0400 Subject: [PATCH 382/465] mapped user info and server config interceptors to only interactive portions of the site, closes #1206 --- .../webapp/WEB-INF/application-context.xml | 39 +++++++++++++++++-- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/application-context.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/application-context.xml index 49cb8d3e95..4f70b20a04 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/application-context.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/application-context.xml @@ -44,10 +44,41 @@ - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From cc0622edd0f754b853963735337f93b7b7c14092 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 12 Apr 2017 14:59:18 -0400 Subject: [PATCH 383/465] internalized random string generation for device codes --- .../mitre/oauth2/service/DeviceCodeService.java | 2 +- .../service/impl/DefaultDeviceCodeService.java | 12 +++++++++++- .../java/org/mitre/oauth2/web/DeviceEndpoint.java | 14 +++----------- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java b/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java index 35968b9e07..f75a4b2910 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java @@ -66,7 +66,7 @@ public interface DeviceCodeService { * @param parameters * @return */ - public DeviceCode createNewDeviceCode(String deviceCode, String userCode, Set requestedScopes, ClientDetailsEntity client, Map parameters); + public DeviceCode createNewDeviceCode(Set requestedScopes, ClientDetailsEntity client, Map parameters); public void clearExpiredDeviceCodes(); diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java index 1d8f6282e8..fcdc12527a 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java @@ -21,6 +21,7 @@ import java.util.Date; import java.util.Map; import java.util.Set; +import java.util.UUID; import org.mitre.data.AbstractPageOperationTemplate; import org.mitre.oauth2.model.AuthenticationHolderEntity; @@ -29,6 +30,7 @@ import org.mitre.oauth2.repository.impl.DeviceCodeRepository; import org.mitre.oauth2.service.DeviceCodeService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.oauth2.common.util.RandomValueStringGenerator; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.stereotype.Service; @@ -44,11 +46,19 @@ public class DefaultDeviceCodeService implements DeviceCodeService { @Autowired private DeviceCodeRepository repository; + private RandomValueStringGenerator randomGenerator = new RandomValueStringGenerator(); + /* (non-Javadoc) * @see org.mitre.oauth2.service.DeviceCodeService#save(org.mitre.oauth2.model.DeviceCode) */ @Override - public DeviceCode createNewDeviceCode(String deviceCode, String userCode, Set requestedScopes, ClientDetailsEntity client, Map parameters) { + public DeviceCode createNewDeviceCode(Set requestedScopes, ClientDetailsEntity client, Map parameters) { + + // create a device code, should be big and random + String deviceCode = UUID.randomUUID().toString(); + + // create a user code, should be random but small and typable + String userCode = randomGenerator.generate(); DeviceCode dc = new DeviceCode(deviceCode, userCode, requestedScopes, client.getClientId(), parameters); diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java index f141e8cce5..f746f85f8e 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java @@ -91,8 +91,6 @@ public class DeviceEndpoint { @Autowired private OAuth2RequestFactory oAuth2RequestFactory; - private RandomValueStringGenerator randomGenerator = new RandomValueStringGenerator(); - @RequestMapping(value = "/" + URL, method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public String requestDeviceCode(@RequestParam("client_id") String clientId, @RequestParam(name="scope", required=false) String scope, Map parameters, ModelMap model) { @@ -134,17 +132,11 @@ public String requestDeviceCode(@RequestParam("client_id") String clientId, @Req // if we got here the request is legit - // create a device code, should be big and random - String deviceCode = UUID.randomUUID().toString(); - - // create a user code, should be random but small and typable - String userCode = randomGenerator.generate(); - - deviceCodeService.createNewDeviceCode(deviceCode, userCode, requestedScopes, client, parameters); + DeviceCode dc = deviceCodeService.createNewDeviceCode(requestedScopes, client, parameters); Map response = new HashMap<>(); - response.put("device_code", deviceCode); - response.put("user_code", userCode); + response.put("device_code", dc.getDeviceCode()); + response.put("user_code", dc.getUserCode()); response.put("verification_uri", config.getIssuer() + USER_URL); if (client.getDeviceCodeValiditySeconds() != null) { response.put("expires_in", client.getDeviceCodeValiditySeconds()); From d317cf502430113717d4c83b3d063cab157f8cbb Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 12 Apr 2017 15:59:17 -0400 Subject: [PATCH 384/465] added exception handling to device code creation step --- .../DeviceCodeCreationException.java | 51 +++++++++++++++++++ .../oauth2/service/DeviceCodeService.java | 3 +- .../org/mitre/oauth2/web/DeviceEndpoint.java | 36 ++++++++----- 3 files changed, 76 insertions(+), 14 deletions(-) create mode 100644 openid-connect-common/src/main/java/org/mitre/oauth2/exception/DeviceCodeCreationException.java diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/exception/DeviceCodeCreationException.java b/openid-connect-common/src/main/java/org/mitre/oauth2/exception/DeviceCodeCreationException.java new file mode 100644 index 0000000000..a4dd7d1caf --- /dev/null +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/exception/DeviceCodeCreationException.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright 2017 The MITRE Corporation + * and the MIT Internet Trust Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +package org.mitre.oauth2.exception; + +/** + * @author jricher + * + */ +public class DeviceCodeCreationException extends Exception { + + private static final long serialVersionUID = 8078568710169208466L; + + private String error; + + public DeviceCodeCreationException(String error, String message) { + super(message); + this.error = error; + } + + /** + * @return the error + */ + public String getError() { + return error; + } + + /** + * @param error the error to set + */ + public void setError(String error) { + this.error = error; + } + + + +} diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java b/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java index f75a4b2910..aa7fa7b863 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/service/DeviceCodeService.java @@ -20,6 +20,7 @@ import java.util.Map; import java.util.Set; +import org.mitre.oauth2.exception.DeviceCodeCreationException; import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.model.DeviceCode; import org.springframework.security.oauth2.provider.ClientDetails; @@ -66,7 +67,7 @@ public interface DeviceCodeService { * @param parameters * @return */ - public DeviceCode createNewDeviceCode(Set requestedScopes, ClientDetailsEntity client, Map parameters); + public DeviceCode createNewDeviceCode(Set requestedScopes, ClientDetailsEntity client, Map parameters) throws DeviceCodeCreationException; public void clearExpiredDeviceCodes(); diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java index f746f85f8e..580732dff3 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java @@ -27,6 +27,7 @@ import javax.servlet.http.HttpSession; +import org.mitre.oauth2.exception.DeviceCodeCreationException; import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.model.DeviceCode; import org.mitre.oauth2.model.SystemScope; @@ -132,21 +133,30 @@ public String requestDeviceCode(@RequestParam("client_id") String clientId, @Req // if we got here the request is legit - DeviceCode dc = deviceCodeService.createNewDeviceCode(requestedScopes, client, parameters); - - Map response = new HashMap<>(); - response.put("device_code", dc.getDeviceCode()); - response.put("user_code", dc.getUserCode()); - response.put("verification_uri", config.getIssuer() + USER_URL); - if (client.getDeviceCodeValiditySeconds() != null) { - response.put("expires_in", client.getDeviceCodeValiditySeconds()); + try { + DeviceCode dc = deviceCodeService.createNewDeviceCode(requestedScopes, client, parameters); + + Map response = new HashMap<>(); + response.put("device_code", dc.getDeviceCode()); + response.put("user_code", dc.getUserCode()); + response.put("verification_uri", config.getIssuer() + USER_URL); + if (client.getDeviceCodeValiditySeconds() != null) { + response.put("expires_in", client.getDeviceCodeValiditySeconds()); + } + + model.put(JsonEntityView.ENTITY, response); + + + return JsonEntityView.VIEWNAME; + } catch (DeviceCodeCreationException dcce) { + + model.put(HttpCodeView.CODE, HttpStatus.BAD_REQUEST); + model.put(JsonErrorView.ERROR, dcce.getError()); + model.put(JsonErrorView.ERROR_MESSAGE, dcce.getMessage()); + + return JsonErrorView.VIEWNAME; } - model.put(JsonEntityView.ENTITY, response); - - - return JsonEntityView.VIEWNAME; - } @PreAuthorize("hasRole('ROLE_USER')") From 45ea899de8aa6b15b60409285a1bb744ef2b1c55 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 12 Apr 2017 16:00:23 -0400 Subject: [PATCH 385/465] made user codes case insensitive --- .../oauth2/service/impl/DefaultDeviceCodeService.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java index fcdc12527a..2dc8c23619 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java @@ -57,8 +57,8 @@ public DeviceCode createNewDeviceCode(Set requestedScopes, ClientDetails // create a device code, should be big and random String deviceCode = UUID.randomUUID().toString(); - // create a user code, should be random but small and typable - String userCode = randomGenerator.generate(); + // create a user code, should be random but small and typable, and always uppercase (lookup is case insensitive) + String userCode = randomGenerator.generate().toUpperCase(); DeviceCode dc = new DeviceCode(deviceCode, userCode, requestedScopes, client.getClientId(), parameters); @@ -76,7 +76,8 @@ public DeviceCode createNewDeviceCode(Set requestedScopes, ClientDetails */ @Override public DeviceCode lookUpByUserCode(String userCode) { - return repository.getByUserCode(userCode); + // always up-case the code for lookup + return repository.getByUserCode(userCode.toUpperCase()); } /* (non-Javadoc) From 702a775881b29d75e78d845b50c476e83c159c00 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Thu, 13 Apr 2017 11:50:57 -0400 Subject: [PATCH 386/465] handle creation time stamp in clients, closes #1210 --- .../openid/connect/service/impl/MITREidDataService_1_3.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_3.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_3.java index 582d17f32c..2f922f9ed4 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_3.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_3.java @@ -529,6 +529,7 @@ private void writeClients(JsonWriter writer) { writer.name(SOFTWARE_ID).value(client.getSoftwareId()); writer.name(SOFTWARE_VERSION).value(client.getSoftwareVersion()); writer.name(SOFTWARE_STATEMENT).value(client.getSoftwareStatement() != null ? client.getSoftwareStatement().serialize() : null); + writer.name(CREATION_DATE).value(toUTCString(client.getCreatedAt())); writer.endObject(); logger.debug("Wrote client {}", client.getId()); } catch (IOException ex) { @@ -1169,6 +1170,9 @@ private void readClients(JsonReader reader) throws IOException { } catch (ParseException e) { logger.error("Couldn't parse software statement", e); } + } else if (name.equals(CREATION_DATE)) { + Date date = utcToDate(reader.nextString()); + client.setCreatedAt(date); } else { logger.debug("Found unexpected entry"); reader.skipValue(); From 11f3cccab95f84009f6cdbd203c54243b9a94954 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 14 Apr 2017 14:42:49 -0400 Subject: [PATCH 387/465] fix JWKS parsing in software statements, closes #1220 --- .../src/main/java/org/mitre/openid/connect/web/ClientAPI.java | 2 +- .../openid/connect/web/DynamicClientRegistrationEndpoint.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java index 7d924f14d8..9f9f4e0ae0 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java @@ -608,7 +608,7 @@ private ClientDetailsEntity validateSoftwareStatement(ClientDetailsEntity newCli newClient.setJwksUri(claimSet.getStringClaim(claim)); break; case JWKS: - newClient.setJwks(JWKSet.parse(claimSet.getStringClaim(claim))); + newClient.setJwks(JWKSet.parse(claimSet.getJSONObjectClaim(claim).toJSONString())); break; case POLICY_URI: newClient.setPolicyUri(claimSet.getStringClaim(claim)); diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java index f99e5cc669..c95dca5457 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java @@ -688,7 +688,7 @@ private ClientDetailsEntity validateSoftwareStatement(ClientDetailsEntity newCli newClient.setJwksUri(claimSet.getStringClaim(claim)); break; case JWKS: - newClient.setJwks(JWKSet.parse(claimSet.getStringClaim(claim))); + newClient.setJwks(JWKSet.parse(claimSet.getJSONObjectClaim(claim).toJSONString())); break; case POLICY_URI: newClient.setPolicyUri(claimSet.getStringClaim(claim)); From 0d564d97144a898b3efc1b9ec99191985084e811 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 14 Apr 2017 15:27:16 -0400 Subject: [PATCH 388/465] made token service transactional, closes #1222 --- .../service/impl/DefaultOAuth2ProviderTokenService.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java index 6b9d2d9aff..fe256243b9 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java @@ -62,6 +62,7 @@ import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.token.TokenEnhancer; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import com.google.common.collect.Sets; import com.nimbusds.jose.util.Base64URL; @@ -177,6 +178,7 @@ private OAuth2RefreshTokenEntity clearExpiredRefreshToken(OAuth2RefreshTokenEnti } @Override + @Transactional(value="defaultTransactionManager") public OAuth2AccessTokenEntity createAccessToken(OAuth2Authentication authentication) throws AuthenticationException, InvalidClientException { if (authentication != null && authentication.getOAuth2Request() != null) { // look up our client @@ -310,6 +312,7 @@ private OAuth2RefreshTokenEntity createRefreshToken(ClientDetailsEntity client, } @Override + @Transactional(value="defaultTransactionManager") public OAuth2AccessTokenEntity refreshAccessToken(String refreshTokenValue, TokenRequest authRequest) throws AuthenticationException { OAuth2RefreshTokenEntity refreshToken = clearExpiredRefreshToken(tokenRepository.getRefreshTokenByValue(refreshTokenValue)); @@ -455,6 +458,7 @@ public OAuth2RefreshTokenEntity getRefreshToken(String refreshTokenValue) throws * Revoke a refresh token and all access tokens issued to it. */ @Override + @Transactional(value="defaultTransactionManager") public void revokeRefreshToken(OAuth2RefreshTokenEntity refreshToken) { tokenRepository.clearAccessTokensForRefreshToken(refreshToken); tokenRepository.removeRefreshToken(refreshToken); @@ -464,6 +468,7 @@ public void revokeRefreshToken(OAuth2RefreshTokenEntity refreshToken) { * Revoke an access token. */ @Override + @Transactional(value="defaultTransactionManager") public void revokeAccessToken(OAuth2AccessTokenEntity accessToken) { tokenRepository.removeAccessToken(accessToken); } @@ -533,6 +538,7 @@ public void doOperation(AuthenticationHolderEntity item) { * @see org.mitre.oauth2.service.OAuth2TokenEntityService#saveAccessToken(org.mitre.oauth2.model.OAuth2AccessTokenEntity) */ @Override + @Transactional(value="defaultTransactionManager") public OAuth2AccessTokenEntity saveAccessToken(OAuth2AccessTokenEntity accessToken) { OAuth2AccessTokenEntity newToken = tokenRepository.saveAccessToken(accessToken); @@ -548,6 +554,7 @@ public OAuth2AccessTokenEntity saveAccessToken(OAuth2AccessTokenEntity accessTok * @see org.mitre.oauth2.service.OAuth2TokenEntityService#saveRefreshToken(org.mitre.oauth2.model.OAuth2RefreshTokenEntity) */ @Override + @Transactional(value="defaultTransactionManager") public OAuth2RefreshTokenEntity saveRefreshToken(OAuth2RefreshTokenEntity refreshToken) { return tokenRepository.saveRefreshToken(refreshToken); } From 0aedfc8e227c311a0dd7ad72cf050fcdd52c92be Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 14 Apr 2017 17:21:50 -0400 Subject: [PATCH 389/465] minor cleanup --- .../src/main/webapp/WEB-INF/views/login.jsp | 1 - 1 file changed, 1 deletion(-) diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/login.jsp b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/login.jsp index fb71cab2a2..5be8f9b2a5 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/login.jsp +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/login.jsp @@ -3,7 +3,6 @@ <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix="o" tagdir="/WEB-INF/tags"%> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> - \ No newline at end of file + From 1feb0958bd0757eb4452ed3d2aeb9b002e9260cd Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 7 Feb 2018 09:09:07 -0500 Subject: [PATCH 424/465] prepare for release --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d1bc15d86..159e487317 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ Unreleased: + +*1.3.2: - Added changelog - Set default redirect URI resolver strict matching to true - Fixed XSS vulnerability on redirect URI display on approval page From f72e6b3e08a5f9b85b7fcc6673055cb144164288 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 7 Feb 2018 09:14:10 -0500 Subject: [PATCH 425/465] [maven-release-plugin] prepare release mitreid-connect-1.3.2 --- openid-connect-client/pom.xml | 2 +- openid-connect-common/pom.xml | 2 +- openid-connect-server-webapp/pom.xml | 2 +- openid-connect-server/pom.xml | 2 +- pom.xml | 2 +- uma-server-webapp/pom.xml | 2 +- uma-server/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/openid-connect-client/pom.xml b/openid-connect-client/pom.xml index 31467161c1..ffebb6025f 100644 --- a/openid-connect-client/pom.xml +++ b/openid-connect-client/pom.xml @@ -22,7 +22,7 @@ openid-connect-parent org.mitre - 1.3.2-SNAPSHOT + 1.3.2 .. openid-connect-client diff --git a/openid-connect-common/pom.xml b/openid-connect-common/pom.xml index b01cd971be..d1863fd7da 100644 --- a/openid-connect-common/pom.xml +++ b/openid-connect-common/pom.xml @@ -22,7 +22,7 @@ openid-connect-parent org.mitre - 1.3.2-SNAPSHOT + 1.3.2 .. openid-connect-common diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index b96cb4b39f..1e072cf5a2 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -21,7 +21,7 @@ org.mitre openid-connect-parent - 1.3.2-SNAPSHOT + 1.3.2 openid-connect-server-webapp war diff --git a/openid-connect-server/pom.xml b/openid-connect-server/pom.xml index f3650b984a..a789a82e5a 100644 --- a/openid-connect-server/pom.xml +++ b/openid-connect-server/pom.xml @@ -23,7 +23,7 @@ org.mitre openid-connect-parent - 1.3.2-SNAPSHOT + 1.3.2 .. diff --git a/pom.xml b/pom.xml index 4ef0bc8c03..3df892977b 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.mitre openid-connect-parent - 1.3.2-SNAPSHOT + 1.3.2 MITREid Connect pom diff --git a/uma-server-webapp/pom.xml b/uma-server-webapp/pom.xml index 5c2d8ebf15..96d7797984 100644 --- a/uma-server-webapp/pom.xml +++ b/uma-server-webapp/pom.xml @@ -19,7 +19,7 @@ org.mitre openid-connect-parent - 1.3.2-SNAPSHOT + 1.3.2 .. uma-server-webapp diff --git a/uma-server/pom.xml b/uma-server/pom.xml index f956423b2d..6a7b061a2b 100644 --- a/uma-server/pom.xml +++ b/uma-server/pom.xml @@ -19,7 +19,7 @@ org.mitre openid-connect-parent - 1.3.2-SNAPSHOT + 1.3.2 .. uma-server From b804f22bc879a391ecbecf3dcc99325a6a803ee8 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Wed, 7 Feb 2018 09:14:16 -0500 Subject: [PATCH 426/465] [maven-release-plugin] prepare for next development iteration --- openid-connect-client/pom.xml | 2 +- openid-connect-common/pom.xml | 2 +- openid-connect-server-webapp/pom.xml | 2 +- openid-connect-server/pom.xml | 2 +- pom.xml | 2 +- uma-server-webapp/pom.xml | 2 +- uma-server/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/openid-connect-client/pom.xml b/openid-connect-client/pom.xml index ffebb6025f..d3bd77eb6b 100644 --- a/openid-connect-client/pom.xml +++ b/openid-connect-client/pom.xml @@ -22,7 +22,7 @@ openid-connect-parent org.mitre - 1.3.2 + 1.3.3-SNAPSHOT .. openid-connect-client diff --git a/openid-connect-common/pom.xml b/openid-connect-common/pom.xml index d1863fd7da..6b7772cd40 100644 --- a/openid-connect-common/pom.xml +++ b/openid-connect-common/pom.xml @@ -22,7 +22,7 @@ openid-connect-parent org.mitre - 1.3.2 + 1.3.3-SNAPSHOT .. openid-connect-common diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index 1e072cf5a2..6bc66e4f99 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -21,7 +21,7 @@ org.mitre openid-connect-parent - 1.3.2 + 1.3.3-SNAPSHOT openid-connect-server-webapp war diff --git a/openid-connect-server/pom.xml b/openid-connect-server/pom.xml index a789a82e5a..1462be27ea 100644 --- a/openid-connect-server/pom.xml +++ b/openid-connect-server/pom.xml @@ -23,7 +23,7 @@ org.mitre openid-connect-parent - 1.3.2 + 1.3.3-SNAPSHOT .. diff --git a/pom.xml b/pom.xml index 3df892977b..72d9126efc 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.mitre openid-connect-parent - 1.3.2 + 1.3.3-SNAPSHOT MITREid Connect pom diff --git a/uma-server-webapp/pom.xml b/uma-server-webapp/pom.xml index 96d7797984..8ce3302da1 100644 --- a/uma-server-webapp/pom.xml +++ b/uma-server-webapp/pom.xml @@ -19,7 +19,7 @@ org.mitre openid-connect-parent - 1.3.2 + 1.3.3-SNAPSHOT .. uma-server-webapp diff --git a/uma-server/pom.xml b/uma-server/pom.xml index 6a7b061a2b..2191615285 100644 --- a/uma-server/pom.xml +++ b/uma-server/pom.xml @@ -19,7 +19,7 @@ org.mitre openid-connect-parent - 1.3.2 + 1.3.3-SNAPSHOT .. uma-server From d119559d4d3d2fae141aed63d112328c8f8b2c6c Mon Sep 17 00:00:00 2001 From: Mark Janssen Date: Thu, 8 Feb 2018 21:03:31 +0100 Subject: [PATCH 427/465] Upgrade to Spring Security 4.2.4 https://spring.io/blog/2018/01/30/cve-2018-1199-spring-security-5-0-1-4-2-4-4-1-5-released --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 72d9126efc..06466d2ab0 100644 --- a/pom.xml +++ b/pom.xml @@ -386,7 +386,7 @@ org.springframework.security spring-security-bom - 4.2.2.RELEASE + 4.2.4.RELEASE pom import From e2d94f422a09a463854ff0919d560641cd06ef23 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 12 Feb 2018 10:39:04 -0500 Subject: [PATCH 428/465] new year 2018 --- LICENSE.txt | 2 +- README.md | 2 +- README_zh_CN.md | 2 +- checkstyle.xml | 2 +- openid-connect-client/pom.xml | 2 +- .../oauth2/introspectingfilter/IntrospectingTokenService.java | 2 +- .../oauth2/introspectingfilter/OAuth2AccessTokenImpl.java | 2 +- .../service/IntrospectionAuthorityGranter.java | 2 +- .../service/IntrospectionConfigurationService.java | 2 +- .../impl/JWTParsingIntrospectionConfigurationService.java | 2 +- .../impl/ScopeBasedIntrospectionAuthoritiesGranter.java | 2 +- .../service/impl/SimpleIntrospectionAuthorityGranter.java | 2 +- .../service/impl/StaticIntrospectionConfigurationService.java | 2 +- .../openid/connect/client/AuthorizationEndpointException.java | 2 +- .../openid/connect/client/NamedAdminAuthoritiesMapper.java | 2 +- .../mitre/openid/connect/client/OIDCAuthenticationFilter.java | 2 +- .../openid/connect/client/OIDCAuthenticationProvider.java | 2 +- .../mitre/openid/connect/client/OIDCAuthoritiesMapper.java | 2 +- .../connect/client/StaticPrefixTargetLinkURIChecker.java | 2 +- .../openid/connect/client/SubjectIssuerGrantedAuthority.java | 2 +- .../org/mitre/openid/connect/client/TargetLinkURIChecker.java | 2 +- .../java/org/mitre/openid/connect/client/UserInfoFetcher.java | 2 +- .../connect/client/keypublisher/ClientKeyPublisher.java | 2 +- .../client/keypublisher/ClientKeyPublisherMapping.java | 2 +- .../openid/connect/client/keypublisher/JwkViewResolver.java | 2 +- .../openid/connect/client/model/IssuerServiceResponse.java | 2 +- .../connect/client/service/AuthRequestOptionsService.java | 2 +- .../openid/connect/client/service/AuthRequestUrlBuilder.java | 2 +- .../connect/client/service/ClientConfigurationService.java | 2 +- .../mitre/openid/connect/client/service/IssuerService.java | 2 +- .../connect/client/service/RegisteredClientService.java | 2 +- .../connect/client/service/ServerConfigurationService.java | 2 +- .../impl/DynamicRegistrationClientConfigurationService.java | 2 +- .../service/impl/DynamicServerConfigurationService.java | 2 +- .../client/service/impl/EncryptedAuthRequestUrlBuilder.java | 2 +- .../client/service/impl/HybridClientConfigurationService.java | 2 +- .../connect/client/service/impl/HybridIssuerService.java | 2 +- .../client/service/impl/HybridServerConfigurationService.java | 2 +- .../client/service/impl/InMemoryRegisteredClientService.java | 2 +- .../client/service/impl/JsonFileRegisteredClientService.java | 2 +- .../client/service/impl/PlainAuthRequestUrlBuilder.java | 2 +- .../client/service/impl/SignedAuthRequestUrlBuilder.java | 2 +- .../client/service/impl/StaticAuthRequestOptionsService.java | 2 +- .../client/service/impl/StaticClientConfigurationService.java | 2 +- .../client/service/impl/StaticServerConfigurationService.java | 2 +- .../client/service/impl/StaticSingleIssuerService.java | 2 +- .../connect/client/service/impl/ThirdPartyIssuerService.java | 2 +- .../connect/client/service/impl/WebfingerIssuerService.java | 2 +- .../oauth2/introspectingfilter/TestOAuth2AccessTokenImpl.java | 2 +- .../impl/TestScopeBasedIntrospectionAuthoritiesGranter.java | 2 +- .../openid/connect/client/TestOIDCAuthenticationFilter.java | 2 +- .../service/impl/TestHybridClientConfigurationService.java | 2 +- .../service/impl/TestHybridServerConfigurationService.java | 2 +- .../client/service/impl/TestPlainAuthRequestUrlBuilder.java | 2 +- .../client/service/impl/TestSignedAuthRequestUrlBuilder.java | 2 +- .../service/impl/TestStaticClientConfigurationService.java | 2 +- .../service/impl/TestStaticServerConfigurationService.java | 2 +- .../client/service/impl/TestThirdPartyIssuerService.java | 2 +- openid-connect-client/src/test/resources/test-context.xml | 2 +- openid-connect-common/pom.xml | 2 +- .../java/org/mitre/data/AbstractPageOperationTemplate.java | 2 +- .../src/main/java/org/mitre/data/DefaultPageCriteria.java | 2 +- .../src/main/java/org/mitre/data/PageCriteria.java | 2 +- .../java/org/mitre/discovery/util/WebfingerURLNormalizer.java | 2 +- .../src/main/java/org/mitre/jose/keystore/JWKSetKeyStore.java | 2 +- .../main/java/org/mitre/jwt/assertion/AssertionValidator.java | 2 +- .../org/mitre/jwt/assertion/impl/NullAssertionValidator.java | 2 +- .../org/mitre/jwt/assertion/impl/SelfAssertionValidator.java | 2 +- .../assertion/impl/WhitelistedIssuerAssertionValidator.java | 2 +- .../encryption/service/JWTEncryptionAndDecryptionService.java | 2 +- .../impl/DefaultJWTEncryptionAndDecryptionService.java | 2 +- .../jwt/signer/service/JWTSigningAndValidationService.java | 2 +- .../mitre/jwt/signer/service/impl/ClientKeyCacheService.java | 2 +- .../service/impl/DefaultJWTSigningAndValidationService.java | 2 +- .../org/mitre/jwt/signer/service/impl/JWKSetCacheService.java | 2 +- .../service/impl/SymmetricKeyJWTValidatorCacheService.java | 2 +- .../mitre/oauth2/exception/DeviceCodeCreationException.java | 2 +- .../org/mitre/oauth2/model/AuthenticationHolderEntity.java | 2 +- .../java/org/mitre/oauth2/model/AuthorizationCodeEntity.java | 2 +- .../main/java/org/mitre/oauth2/model/ClientDetailsEntity.java | 2 +- .../src/main/java/org/mitre/oauth2/model/DeviceCode.java | 2 +- .../java/org/mitre/oauth2/model/OAuth2AccessTokenEntity.java | 2 +- .../java/org/mitre/oauth2/model/OAuth2RefreshTokenEntity.java | 2 +- .../src/main/java/org/mitre/oauth2/model/PKCEAlgorithm.java | 2 +- .../main/java/org/mitre/oauth2/model/RegisteredClient.java | 2 +- .../java/org/mitre/oauth2/model/RegisteredClientFields.java | 2 +- .../java/org/mitre/oauth2/model/SavedUserAuthentication.java | 2 +- .../src/main/java/org/mitre/oauth2/model/SystemScope.java | 2 +- .../oauth2/model/convert/JWEAlgorithmStringConverter.java | 2 +- .../model/convert/JWEEncryptionMethodStringConverter.java | 2 +- .../org/mitre/oauth2/model/convert/JWKSetStringConverter.java | 2 +- .../oauth2/model/convert/JWSAlgorithmStringConverter.java | 2 +- .../org/mitre/oauth2/model/convert/JWTStringConverter.java | 2 +- .../oauth2/model/convert/JsonElementStringConverter.java | 2 +- .../oauth2/model/convert/PKCEAlgorithmStringConverter.java | 2 +- .../oauth2/model/convert/SerializableStringConverter.java | 2 +- .../model/convert/SimpleGrantedAuthorityStringConverter.java | 2 +- .../oauth2/repository/AuthenticationHolderRepository.java | 2 +- .../mitre/oauth2/repository/AuthorizationCodeRepository.java | 2 +- .../org/mitre/oauth2/repository/OAuth2ClientRepository.java | 2 +- .../org/mitre/oauth2/repository/OAuth2TokenRepository.java | 2 +- .../org/mitre/oauth2/repository/SystemScopeRepository.java | 2 +- .../mitre/oauth2/repository/impl/DeviceCodeRepository.java | 2 +- .../org/mitre/oauth2/service/ClientDetailsEntityService.java | 2 +- .../main/java/org/mitre/oauth2/service/DeviceCodeService.java | 2 +- .../mitre/oauth2/service/IntrospectionResultAssembler.java | 2 +- .../org/mitre/oauth2/service/OAuth2TokenEntityService.java | 2 +- .../java/org/mitre/oauth2/service/SystemScopeService.java | 2 +- .../oauth2/service/impl/DefaultClientUserDetailsService.java | 2 +- .../service/impl/UriEncodedClientUserDetailsService.java | 2 +- .../openid/connect/ClientDetailsEntityJsonProcessor.java | 2 +- .../connect/config/ConfigurationBeanLocaleResolver.java | 2 +- .../openid/connect/config/ConfigurationPropertiesBean.java | 2 +- .../java/org/mitre/openid/connect/config/JWKSetEditor.java | 2 +- .../org/mitre/openid/connect/config/ServerConfiguration.java | 2 +- .../java/org/mitre/openid/connect/config/UIConfiguration.java | 2 +- .../src/main/java/org/mitre/openid/connect/model/Address.java | 2 +- .../java/org/mitre/openid/connect/model/ApprovedSite.java | 2 +- .../java/org/mitre/openid/connect/model/BlacklistedSite.java | 2 +- .../main/java/org/mitre/openid/connect/model/CachedImage.java | 2 +- .../main/java/org/mitre/openid/connect/model/ClientStat.java | 2 +- .../java/org/mitre/openid/connect/model/DefaultAddress.java | 2 +- .../java/org/mitre/openid/connect/model/DefaultUserInfo.java | 2 +- .../mitre/openid/connect/model/OIDCAuthenticationToken.java | 2 +- .../org/mitre/openid/connect/model/PairwiseIdentifier.java | 2 +- .../openid/connect/model/PendingOIDCAuthenticationToken.java | 2 +- .../main/java/org/mitre/openid/connect/model/UserInfo.java | 2 +- .../java/org/mitre/openid/connect/model/WhitelistedSite.java | 2 +- .../connect/model/convert/JsonObjectStringConverter.java | 2 +- .../mitre/openid/connect/repository/AddressRepository.java | 2 +- .../openid/connect/repository/ApprovedSiteRepository.java | 2 +- .../openid/connect/repository/BlacklistedSiteRepository.java | 2 +- .../connect/repository/PairwiseIdentifierRepository.java | 2 +- .../mitre/openid/connect/repository/UserInfoRepository.java | 2 +- .../openid/connect/repository/WhitelistedSiteRepository.java | 2 +- .../org/mitre/openid/connect/service/ApprovedSiteService.java | 2 +- .../mitre/openid/connect/service/BlacklistedSiteService.java | 2 +- .../openid/connect/service/ClientLogoLoadingService.java | 2 +- .../org/mitre/openid/connect/service/LoginHintExtracter.java | 2 +- .../org/mitre/openid/connect/service/MITREidDataService.java | 2 +- .../openid/connect/service/MITREidDataServiceExtension.java | 2 +- .../mitre/openid/connect/service/MITREidDataServiceMaps.java | 2 +- .../org/mitre/openid/connect/service/OIDCTokenService.java | 2 +- .../openid/connect/service/PairwiseIdentiferService.java | 2 +- .../openid/connect/service/ScopeClaimTranslationService.java | 2 +- .../java/org/mitre/openid/connect/service/StatsService.java | 2 +- .../org/mitre/openid/connect/service/UserInfoService.java | 2 +- .../mitre/openid/connect/service/WhitelistedSiteService.java | 2 +- .../main/java/org/mitre/openid/connect/view/JWKSetView.java | 2 +- .../org/mitre/openid/connect/web/UserInfoInterceptor.java | 2 +- .../src/main/java/org/mitre/uma/model/Claim.java | 2 +- .../main/java/org/mitre/uma/model/ClaimProcessingResult.java | 2 +- .../src/main/java/org/mitre/uma/model/Permission.java | 2 +- .../src/main/java/org/mitre/uma/model/PermissionTicket.java | 2 +- .../src/main/java/org/mitre/uma/model/Policy.java | 2 +- .../src/main/java/org/mitre/uma/model/ResourceSet.java | 2 +- .../main/java/org/mitre/uma/model/SavedRegisteredClient.java | 2 +- .../uma/model/convert/RegisteredClientStringConverter.java | 2 +- .../java/org/mitre/uma/repository/PermissionRepository.java | 2 +- .../java/org/mitre/uma/repository/ResourceSetRepository.java | 2 +- .../java/org/mitre/uma/service/ClaimsProcessingService.java | 2 +- .../main/java/org/mitre/uma/service/PermissionService.java | 2 +- .../main/java/org/mitre/uma/service/ResourceSetService.java | 2 +- .../org/mitre/uma/service/SavedRegisteredClientService.java | 2 +- .../src/main/java/org/mitre/uma/service/UmaTokenService.java | 2 +- .../src/main/java/org/mitre/util/JsonUtils.java | 2 +- .../src/main/java/org/mitre/util/jpa/JpaUtil.java | 2 +- .../org/mitre/data/AbstractPageOperationTemplateTest.java | 2 +- .../org/mitre/discovery/util/TestWebfingerURLNormalizer.java | 2 +- .../src/test/java/org/mitre/jose/TestJWKSetKeyStore.java | 2 +- .../impl/TestDefaultJWTEncryptionAndDecryptionService.java | 2 +- .../java/org/mitre/oauth2/model/ClientDetailsEntityTest.java | 2 +- .../java/org/mitre/oauth2/model/RegisteredClientTest.java | 2 +- .../openid/connect/ClientDetailsEntityJsonProcessorTest.java | 2 +- .../connect/config/ConfigurationPropertiesBeanTest.java | 2 +- .../mitre/openid/connect/config/ServerConfigurationTest.java | 2 +- openid-connect-server-webapp/pom.xml | 2 +- .../src/main/resources/db/oracle/entity-mappings_oracle.xml | 2 +- openid-connect-server-webapp/src/main/resources/log4j.xml | 2 +- .../src/main/webapp/WEB-INF/application-context.xml | 2 +- .../src/main/webapp/WEB-INF/assertion-config.xml | 2 +- .../src/main/webapp/WEB-INF/authz-config.xml | 2 +- .../src/main/webapp/WEB-INF/crypto-config.xml | 2 +- .../src/main/webapp/WEB-INF/data-context.xml | 2 +- .../src/main/webapp/WEB-INF/endpoint-config.xml | 2 +- .../src/main/webapp/WEB-INF/jpa-config.xml | 2 +- .../src/main/webapp/WEB-INF/local-config.xml | 2 +- .../src/main/webapp/WEB-INF/locale-config.xml | 2 +- .../src/main/webapp/WEB-INF/server-config.xml | 2 +- .../src/main/webapp/WEB-INF/spring-servlet.xml | 2 +- .../src/main/webapp/WEB-INF/task-config.xml | 2 +- .../src/main/webapp/WEB-INF/ui-config.xml | 2 +- .../src/main/webapp/WEB-INF/user-context.xml | 2 +- openid-connect-server-webapp/src/main/webapp/WEB-INF/web.xml | 2 +- .../src/main/webapp/WEB-INF/wro.properties | 2 +- openid-connect-server-webapp/src/main/webapp/WEB-INF/wro.xml | 2 +- .../src/main/webapp/resources/js/admin.js | 2 +- .../src/main/webapp/resources/js/blacklist.js | 2 +- .../src/main/webapp/resources/js/client.js | 2 +- .../src/main/webapp/resources/js/dynreg.js | 2 +- .../src/main/webapp/resources/js/grant.js | 2 +- .../src/main/webapp/resources/js/locale/en/messages.json | 2 +- .../src/main/webapp/resources/js/locale/fr/messages.json | 2 +- .../src/main/webapp/resources/js/profile.js | 2 +- .../src/main/webapp/resources/js/rsreg.js | 2 +- .../src/main/webapp/resources/js/scope.js | 2 +- .../src/main/webapp/resources/js/token.js | 2 +- .../src/main/webapp/resources/js/whitelist.js | 2 +- .../src/main/webapp/resources/template/admin.html | 2 +- .../src/main/webapp/resources/template/blacklist.html | 2 +- .../src/main/webapp/resources/template/client.html | 2 +- .../src/main/webapp/resources/template/dynreg.html | 2 +- .../src/main/webapp/resources/template/grant.html | 2 +- .../src/main/webapp/resources/template/rsreg.html | 2 +- .../src/main/webapp/resources/template/scope.html | 2 +- .../src/main/webapp/resources/template/token.html | 2 +- .../src/main/webapp/resources/template/whitelist.html | 2 +- openid-connect-server/pom.xml | 2 +- .../src/main/java/org/mitre/discovery/view/WebfingerView.java | 2 +- .../main/java/org/mitre/discovery/web/DiscoveryEndpoint.java | 2 +- .../mitre/oauth2/assertion/AssertionOAuth2RequestFactory.java | 2 +- .../mitre/oauth2/assertion/impl/DirectCopyRequestFactory.java | 2 +- .../mitre/oauth2/exception/AuthorizationPendingException.java | 2 +- .../mitre/oauth2/exception/DeviceCodeExpiredException.java | 2 +- .../mitre/oauth2/exception/DuplicateClientIdException.java | 2 +- .../repository/impl/JpaAuthenticationHolderRepository.java | 2 +- .../repository/impl/JpaAuthorizationCodeRepository.java | 2 +- .../mitre/oauth2/repository/impl/JpaDeviceCodeRepository.java | 2 +- .../oauth2/repository/impl/JpaOAuth2ClientRepository.java | 2 +- .../oauth2/repository/impl/JpaOAuth2TokenRepository.java | 2 +- .../oauth2/repository/impl/JpaSystemScopeRepository.java | 2 +- .../oauth2/service/impl/BlacklistAwareRedirectResolver.java | 2 +- .../mitre/oauth2/service/impl/DefaultDeviceCodeService.java | 2 +- .../service/impl/DefaultIntrospectionResultAssembler.java | 2 +- .../service/impl/DefaultOAuth2AuthorizationCodeService.java | 2 +- .../service/impl/DefaultOAuth2ClientDetailsEntityService.java | 2 +- .../service/impl/DefaultOAuth2ProviderTokenService.java | 2 +- .../mitre/oauth2/service/impl/DefaultSystemScopeService.java | 2 +- .../main/java/org/mitre/oauth2/token/ChainedTokenGranter.java | 2 +- .../main/java/org/mitre/oauth2/token/DeviceTokenGranter.java | 2 +- .../java/org/mitre/oauth2/token/JWTAssertionTokenGranter.java | 2 +- .../oauth2/token/ScopeServiceAwareOAuth2RequestValidator.java | 2 +- .../src/main/java/org/mitre/oauth2/view/TokenApiView.java | 2 +- .../java/org/mitre/oauth2/web/AuthenticationUtilities.java | 2 +- .../src/main/java/org/mitre/oauth2/web/CorsFilter.java | 2 +- .../src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java | 2 +- .../main/java/org/mitre/oauth2/web/IntrospectionEndpoint.java | 2 +- .../java/org/mitre/oauth2/web/OAuth2ExceptionHandler.java | 2 +- .../org/mitre/oauth2/web/OAuthConfirmationController.java | 2 +- .../main/java/org/mitre/oauth2/web/RevocationEndpoint.java | 2 +- .../src/main/java/org/mitre/oauth2/web/ScopeAPI.java | 2 +- .../src/main/java/org/mitre/oauth2/web/TokenAPI.java | 2 +- .../assertion/JWTBearerAssertionAuthenticationToken.java | 2 +- .../connect/assertion/JWTBearerAuthenticationProvider.java | 2 +- .../JWTBearerClientAssertionTokenEndpointFilter.java | 2 +- .../org/mitre/openid/connect/config/JsonMessageSource.java | 2 +- .../mitre/openid/connect/exception/ValidationException.java | 4 ++-- .../openid/connect/filter/AuthorizationRequestFilter.java | 2 +- .../mitre/openid/connect/filter/MultiUrlRequestMatcher.java | 2 +- .../openid/connect/repository/impl/JpaAddressRepository.java | 2 +- .../connect/repository/impl/JpaApprovedSiteRepository.java | 2 +- .../connect/repository/impl/JpaBlacklistedSiteRepository.java | 2 +- .../repository/impl/JpaPairwiseIdentifierRepository.java | 2 +- .../openid/connect/repository/impl/JpaUserInfoRepository.java | 2 +- .../connect/repository/impl/JpaWhitelistedSiteRepository.java | 2 +- .../openid/connect/request/ConnectOAuth2RequestFactory.java | 2 +- .../openid/connect/request/ConnectRequestParameters.java | 2 +- .../connect/service/impl/DefaultApprovedSiteService.java | 2 +- .../connect/service/impl/DefaultBlacklistedSiteService.java | 2 +- .../openid/connect/service/impl/DefaultOIDCTokenService.java | 2 +- .../service/impl/DefaultScopeClaimTranslationService.java | 2 +- .../openid/connect/service/impl/DefaultStatsService.java | 2 +- .../openid/connect/service/impl/DefaultUserInfoService.java | 2 +- .../connect/service/impl/DefaultWhitelistedSiteService.java | 2 +- .../openid/connect/service/impl/DummyResourceSetService.java | 2 +- .../service/impl/InMemoryClientLogoLoadingService.java | 2 +- .../connect/service/impl/MITREidDataServiceSupport.java | 2 +- .../openid/connect/service/impl/MITREidDataService_1_0.java | 2 +- .../openid/connect/service/impl/MITREidDataService_1_1.java | 2 +- .../openid/connect/service/impl/MITREidDataService_1_2.java | 2 +- .../openid/connect/service/impl/MITREidDataService_1_3.java | 2 +- .../connect/service/impl/MatchLoginHintsAgainstUsers.java | 2 +- .../mitre/openid/connect/service/impl/PassAllLoginHints.java | 2 +- .../openid/connect/service/impl/RemoveLoginHintsWithHTTP.java | 2 +- .../connect/service/impl/UUIDPairwiseIdentiferService.java | 2 +- .../org/mitre/openid/connect/token/ConnectTokenEnhancer.java | 2 +- .../mitre/openid/connect/token/TofuUserApprovalHandler.java | 2 +- .../java/org/mitre/openid/connect/util/IdTokenHashUtils.java | 2 +- .../mitre/openid/connect/view/AbstractClientEntityView.java | 2 +- .../mitre/openid/connect/view/ClientEntityViewForAdmins.java | 2 +- .../mitre/openid/connect/view/ClientEntityViewForUsers.java | 2 +- .../openid/connect/view/ClientInformationResponseView.java | 2 +- .../main/java/org/mitre/openid/connect/view/HttpCodeView.java | 2 +- .../org/mitre/openid/connect/view/JsonApprovedSiteView.java | 2 +- .../java/org/mitre/openid/connect/view/JsonEntityView.java | 2 +- .../java/org/mitre/openid/connect/view/JsonErrorView.java | 2 +- .../java/org/mitre/openid/connect/view/UserInfoJWTView.java | 2 +- .../main/java/org/mitre/openid/connect/view/UserInfoView.java | 2 +- .../java/org/mitre/openid/connect/web/ApprovedSiteAPI.java | 2 +- .../mitre/openid/connect/web/AuthenticationTimeStamper.java | 2 +- .../main/java/org/mitre/openid/connect/web/BlacklistAPI.java | 2 +- .../src/main/java/org/mitre/openid/connect/web/ClientAPI.java | 2 +- .../src/main/java/org/mitre/openid/connect/web/DataAPI.java | 4 ++-- .../openid/connect/web/DynamicClientRegistrationEndpoint.java | 2 +- .../java/org/mitre/openid/connect/web/EndSessionEndpoint.java | 2 +- .../mitre/openid/connect/web/JWKSetPublishingEndpoint.java | 2 +- .../connect/web/ProtectedResourceRegistrationEndpoint.java | 2 +- .../java/org/mitre/openid/connect/web/RootController.java | 2 +- .../org/mitre/openid/connect/web/ServerConfigInterceptor.java | 2 +- .../src/main/java/org/mitre/openid/connect/web/StatsAPI.java | 2 +- .../java/org/mitre/openid/connect/web/UserInfoEndpoint.java | 2 +- .../main/java/org/mitre/openid/connect/web/WhitelistAPI.java | 2 +- .../service/impl/TestBlacklistAwareRedirectResolver.java | 2 +- .../service/impl/TestDefaultIntrospectionResultAssembler.java | 2 +- .../impl/TestDefaultOAuth2ClientDetailsEntityService.java | 2 +- .../service/impl/TestDefaultOAuth2ProviderTokenService.java | 2 +- .../oauth2/service/impl/TestDefaultSystemScopeService.java | 2 +- .../connect/service/impl/TestDefaultApprovedSiteService.java | 2 +- .../service/impl/TestDefaultBlacklistedSiteService.java | 2 +- .../openid/connect/service/impl/TestDefaultStatsService.java | 2 +- .../connect/service/impl/TestDefaultUserInfoService.java | 2 +- .../service/impl/TestDefaultWhitelistedSiteService.java | 2 +- .../connect/service/impl/TestMITREidDataService_1_0.java | 2 +- .../connect/service/impl/TestMITREidDataService_1_1.java | 2 +- .../connect/service/impl/TestMITREidDataService_1_2.java | 2 +- .../connect/service/impl/TestMITREidDataService_1_3.java | 2 +- .../service/impl/TestUUIDPairwiseIdentiferService.java | 2 +- .../mitre/openid/connect/token/TestConnectTokenEnhancer.java | 2 +- .../org/mitre/openid/connect/util/TestIdTokenHashUtils.java | 2 +- pom.xml | 2 +- uma-server-webapp/pom.xml | 2 +- uma-server-webapp/src/main/webapp/WEB-INF/endpoint-config.xml | 2 +- uma-server-webapp/src/main/webapp/WEB-INF/server-config.xml | 2 +- uma-server-webapp/src/main/webapp/WEB-INF/ui-config.xml | 2 +- uma-server-webapp/src/main/webapp/WEB-INF/user-context.xml | 2 +- uma-server-webapp/src/main/webapp/resources/js/policy.js | 2 +- .../src/main/webapp/resources/template/policy.html | 2 +- uma-server/pom.xml | 2 +- .../mitre/uma/repository/impl/JpaPermissionRepository.java | 2 +- .../mitre/uma/repository/impl/JpaResourceSetRepository.java | 2 +- .../org/mitre/uma/service/impl/DefaultPermissionService.java | 2 +- .../org/mitre/uma/service/impl/DefaultResourceSetService.java | 2 +- .../org/mitre/uma/service/impl/DefaultUmaTokenService.java | 2 +- .../mitre/uma/service/impl/JpaRegisteredClientService.java | 2 +- .../org/mitre/uma/service/impl/MatchAllClaimsOnAnyPolicy.java | 2 +- .../mitre/uma/service/impl/UmaDataServiceExtension_1_3.java | 2 +- .../org/mitre/uma/util/ExternalLoginAuthoritiesMapper.java | 2 +- .../org/mitre/uma/view/ResourceSetEntityAbbreviatedView.java | 2 +- .../main/java/org/mitre/uma/view/ResourceSetEntityView.java | 2 +- .../java/org/mitre/uma/web/AuthorizationRequestEndpoint.java | 2 +- .../main/java/org/mitre/uma/web/ClaimsCollectionEndpoint.java | 2 +- .../org/mitre/uma/web/PermissionRegistrationEndpoint.java | 2 +- uma-server/src/main/java/org/mitre/uma/web/PolicyAPI.java | 2 +- .../org/mitre/uma/web/ResourceSetRegistrationEndpoint.java | 2 +- .../src/main/java/org/mitre/uma/web/UmaDiscoveryEndpoint.java | 2 +- .../main/java/org/mitre/uma/web/UserClaimSearchHelper.java | 2 +- .../mitre/uma/service/impl/TestDefaultPermissionService.java | 2 +- .../mitre/uma/service/impl/TestDefaultResourceSetService.java | 2 +- 358 files changed, 360 insertions(+), 360 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index be3864a680..0e640e493b 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright 2017 The MIT Internet Trust Consortium +Copyright 2018 The MIT Internet Trust Consortium Portions copyright 2011-2013 The MITRE Corporation diff --git a/README.md b/README.md index 7b9646814f..febfbd6737 100644 --- a/README.md +++ b/README.md @@ -28,4 +28,4 @@ The authors and key contributors of the project include: * [Mark Janssen](https://github.com/praseodym) -Copyright ©2017, [MIT Internet Trust Consortium](http://www.trust.mit.edu/). Licensed under the Apache 2.0 license, for details see `LICENSE.txt`. +Copyright ©2018, [MIT Internet Trust Consortium](http://www.trust.mit.edu/). Licensed under the Apache 2.0 license, for details see `LICENSE.txt`. diff --git a/README_zh_CN.md b/README_zh_CN.md index fecf8aebea..4933b36836 100644 --- a/README_zh_CN.md +++ b/README_zh_CN.md @@ -35,4 +35,4 @@ -版权所有 ©2017 [MIT因特网信任联盟](http://www.mit-trust.org/). 采用Apache 2.0许可证, 详见 `LICENSE.txt`. +版权所有 ©2018 [MIT因特网信任联盟](http://www.mit-trust.org/). 采用Apache 2.0许可证, 详见 `LICENSE.txt`. diff --git a/checkstyle.xml b/checkstyle.xml index 4d12f82d13..06129daddb 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -1,6 +1,6 @@ + + + diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java index 9e2bac67f2..9c54c9f073 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java @@ -138,18 +138,21 @@ public String requestDeviceCode(@RequestParam("client_id") String clientId, @Req try { DeviceCode dc = deviceCodeService.createNewDeviceCode(requestedScopes, client, parameters); - URI verificationUriComplete = new URIBuilder(config.getIssuer() + USER_URL) - .addParameter("user_code", dc.getUserCode()) - .build(); - Map response = new HashMap<>(); response.put("device_code", dc.getDeviceCode()); response.put("user_code", dc.getUserCode()); response.put("verification_uri", config.getIssuer() + USER_URL); - response.put("verification_uri_complete", verificationUriComplete); if (client.getDeviceCodeValiditySeconds() != null) { response.put("expires_in", client.getDeviceCodeValiditySeconds()); } + + if (config.isAllowCompleteDeviceCodeUri()) { + URI verificationUriComplete = new URIBuilder(config.getIssuer() + USER_URL) + .addParameter("user_code", dc.getUserCode()) + .build(); + + response.put("verification_uri_complete", verificationUriComplete.toString()); + } model.put(JsonEntityView.ENTITY, response); @@ -175,8 +178,8 @@ public String requestDeviceCode(@RequestParam("client_id") String clientId, @Req @RequestMapping(value = "/" + USER_URL, method = RequestMethod.GET) public String requestUserCode(@RequestParam(value = "user_code", required = false) String userCode, ModelMap model, HttpSession session) { - if (userCode == null) { - + if (!config.isAllowCompleteDeviceCodeUri() || userCode == null) { + // if we don't allow the complete URI or we didn't get a user code on the way in, // print out a page that asks the user to enter their user code // user must be logged in return "requestUserCode"; From 802e40ebc9a03d96a1d8f46345c8260db9dc9853 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Thu, 3 May 2018 14:52:49 -0400 Subject: [PATCH 445/465] Updated changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 159e487317..5609bc7045 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,12 @@ Unreleased: +- Authorization codes are now longer +- Client/RS can parse the "sub" and "user_id" claims in introspection response +- Database-direct queries for fetching tokens by user (optimization) +- Device flow supports verification_uri_complete (must be turned on) +- Long scopes display properly and are still checkable +- Language system remebers when it can't find a file and stops throwing so many errors +- Index added for refresh tokens +- Updated to Spring Security 4.2.4 *1.3.2: - Added changelog From 69afba59cc53ea2075609c157e9b142fd242f90e Mon Sep 17 00:00:00 2001 From: Angelo Kastroulis Date: Mon, 11 Jun 2018 15:48:09 -0400 Subject: [PATCH 446/465] Corrected create script --- .../src/main/resources/db/oracle/create_db-user | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 openid-connect-server-webapp/src/main/resources/db/oracle/create_db-user diff --git a/openid-connect-server-webapp/src/main/resources/db/oracle/create_db-user b/openid-connect-server-webapp/src/main/resources/db/oracle/create_db-user new file mode 100644 index 0000000000..fdbf9d44fb --- /dev/null +++ b/openid-connect-server-webapp/src/main/resources/db/oracle/create_db-user @@ -0,0 +1,15 @@ +drop user oauth cascade; +drop tablespace data_ts INCLUDING CONTENTS AND DATAFILES; +drop tablespace temp_ts INCLUDING CONTENTS AND DATAFILES; +CREATE TABLESPACE data_ts DATAFILE 'data_ts.dat' SIZE 40M ONLINE; +CREATE TEMPORARY TABLESPACE temp_ts TEMPFILE 'temp_ts.dbf' SIZE 5M AUTOEXTEND ON; +create user oauth identified by test DEFAULT TABLESPACE data_ts QUOTA 500K ON data_ts TEMPORARY TABLESPACE temp_ts; +GRANT CONNECT TO oauth; +GRANT UNLIMITED TABLESPACE TO oauth; +grant create session to oauth; +grant create table to oauth; +GRANT CREATE TABLESPACE TO oauth; +GRANT CREATE VIEW TO oauth; +GRANT CREATE ANY INDEX TO oauth; +GRANT CREATE SEQUENCE TO oauth; +GRANT CREATE SYNONYM TO oauth; From f56918982a22f668a4a519dc950f6e1d9e28c8d8 Mon Sep 17 00:00:00 2001 From: Angelo Kastroulis Date: Mon, 11 Jun 2018 15:50:05 -0400 Subject: [PATCH 447/465] Fixed broken scripts from schema change on system_scope --- .../src/main/resources/db/mysql/scopes.sql | 16 +++++----- .../db/oracle/oracle_database_tables.sql | 7 ++--- .../resources/db/oracle/scopes_oracle.sql | 31 +++++++++---------- .../db/psql/psql_database_tables.sql | 2 -- .../src/main/resources/db/psql/scopes.sql | 18 +++++------ 5 files changed, 34 insertions(+), 40 deletions(-) diff --git a/openid-connect-server-webapp/src/main/resources/db/mysql/scopes.sql b/openid-connect-server-webapp/src/main/resources/db/mysql/scopes.sql index 62d5dcd29a..3768977ec1 100644 --- a/openid-connect-server-webapp/src/main/resources/db/mysql/scopes.sql +++ b/openid-connect-server-webapp/src/main/resources/db/mysql/scopes.sql @@ -10,13 +10,13 @@ START TRANSACTION; -- Insert scope information into the temporary tables. -- -INSERT INTO system_scope_TEMP (scope, description, icon, restricted, default_scope, structured, structured_param_description) VALUES - ('openid', 'log in using your identity', 'user', false, true, false, null), - ('profile', 'basic profile information', 'list-alt', false, true, false, null), - ('email', 'email address', 'envelope', false, true, false, null), - ('address', 'physical address', 'home', false, true, false, null), - ('phone', 'telephone number', 'bell', false, true, false, null), - ('offline_access', 'offline access', 'time', false, false, false, null); +INSERT INTO system_scope_TEMP (scope, description, icon, restricted, default_scope) VALUES + ('openid', 'log in using your identity', 'user', false, true), + ('profile', 'basic profile information', 'list-alt', false, true), + ('email', 'email address', 'envelope', false, true), + ('address', 'physical address', 'home', false, true), + ('phone', 'telephone number', 'bell', false, true), + ('offline_access', 'offline access', 'time', false, false); -- -- Merge the temporary scopes safely into the database. This is a two-step process to keep scopes from being created on every startup with a persistent store. @@ -28,4 +28,4 @@ INSERT INTO system_scope (scope, description, icon, restricted, default_scope, s COMMIT; -SET AUTOCOMMIT = 1; \ No newline at end of file +SET AUTOCOMMIT = 1; diff --git a/openid-connect-server-webapp/src/main/resources/db/oracle/oracle_database_tables.sql b/openid-connect-server-webapp/src/main/resources/db/oracle/oracle_database_tables.sql index 5f88b689bf..9f430adace 100644 --- a/openid-connect-server-webapp/src/main/resources/db/oracle/oracle_database_tables.sql +++ b/openid-connect-server-webapp/src/main/resources/db/oracle/oracle_database_tables.sql @@ -255,14 +255,11 @@ CREATE TABLE system_scope ( description VARCHAR2(4000), icon VARCHAR2(256), restricted NUMBER(1) DEFAULT 0 NOT NULL, - default_scope NUMBER(1) DEFAULT 0 NOT NULL, - structured NUMBER(1) DEFAULT 0 NOT NULL, - structured_param_description VARCHAR2(256), + default_scope NUMBER(1) DEFAULT 0 NOT NULL CONSTRAINT system_scope_unique UNIQUE (scope), CONSTRAINT default_scope_check CHECK (default_scope in (1,0)), - CONSTRAINT restricted_check CHECK (restricted in (1,0)), - CONSTRAINT structured_check CHECK (structured in (1,0)) + CONSTRAINT restricted_check CHECK (restricted in (1,0)) ); CREATE SEQUENCE system_scope_seq START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE; diff --git a/openid-connect-server-webapp/src/main/resources/db/oracle/scopes_oracle.sql b/openid-connect-server-webapp/src/main/resources/db/oracle/scopes_oracle.sql index 98e98bfcbe..bb6bc82a23 100644 --- a/openid-connect-server-webapp/src/main/resources/db/oracle/scopes_oracle.sql +++ b/openid-connect-server-webapp/src/main/resources/db/oracle/scopes_oracle.sql @@ -2,26 +2,25 @@ -- Insert scope information into the temporary tables. -- -INSERT INTO system_scope_TEMP (scope, description, icon, restricted, default_scope, structured, structured_param_description) VALUES - ('openid', 'log in using your identity', 'user', 0, 1, 0, null); -INSERT INTO system_scope_TEMP (scope, description, icon, restricted, default_scope, structured, structured_param_description) VALUES - ('profile', 'basic profile information', 'list-alt', 0, 1, 0, null); -INSERT INTO system_scope_TEMP (scope, description, icon, restricted, default_scope, structured, structured_param_description) VALUES - ('email', 'email address', 'envelope', 0, 1, 0, null); -INSERT INTO system_scope_TEMP (scope, description, icon, restricted, default_scope, structured, structured_param_description) VALUES - ('address', 'physical address', 'home', 0, 1, 0, null); -INSERT INTO system_scope_TEMP (scope, description, icon, restricted, default_scope, structured, structured_param_description) VALUES - ('phone', 'telephone number', 'bell', 0, 1, 0, null); -INSERT INTO system_scope_TEMP (scope, description, icon, restricted, default_scope, structured, structured_param_description) VALUES - ('offline_access', 'offline access', 'time', 0, 0, 0, null); - +INSERT INTO system_scope_TEMP (scope, description, icon, restricted, default_scope) VALUES + ('openid', 'log in using your identity', 'user', 0, 1); +INSERT INTO system_scope_TEMP (scope, description, icon, restricted, default_scope) VALUES + ('profile', 'basic profile information', 'list-alt', 0, 1); +INSERT INTO system_scope_TEMP (scope, description, icon, restricted, default_scope) VALUES + ('email', 'email address', 'envelope', 0, 1); +INSERT INTO system_scope_TEMP (scope, description, icon, restricted, default_scope) VALUES + ('address', 'physical address', 'home', 0, 1); +INSERT INTO system_scope_TEMP (scope, description, icon, restricted, default_scope) VALUES + ('phone', 'telephone number', 'bell', 0, 1, 0); +INSERT INTO system_scope_TEMP (scope, description, icon, restricted, default_scope) VALUES + ('offline_access', 'offline access', 'time', 0, 0); -- -- Merge the temporary scopes safely into the database. This is a two-step process to keep scopes from being created on every startup with a persistent store. -- MERGE INTO system_scope - USING (SELECT scope, description, icon, restricted, default_scope, structured, structured_param_description FROM system_scope_TEMP) vals + USING (SELECT scope, description, icon, restricted, default_scope FROM system_scope_TEMP) vals ON (vals.scope = system_scope.scope) WHEN NOT MATCHED THEN - INSERT (id, scope, description, icon, restricted, default_scope, structured, structured_param_description) VALUES(system_scope_seq.nextval, vals.scope, - vals.description, vals.icon, vals.restricted, vals.default_scope, vals.structured, vals.structured_param_description); \ No newline at end of file + INSERT (id, scope, description, icon, restricted, default_scope) VALUES(system_scope_seq.nextval, vals.scope, + vals.description, vals.icon, vals.restricted, vals.default_scope); diff --git a/openid-connect-server-webapp/src/main/resources/db/psql/psql_database_tables.sql b/openid-connect-server-webapp/src/main/resources/db/psql/psql_database_tables.sql index a9992993f8..be871b7e80 100644 --- a/openid-connect-server-webapp/src/main/resources/db/psql/psql_database_tables.sql +++ b/openid-connect-server-webapp/src/main/resources/db/psql/psql_database_tables.sql @@ -239,8 +239,6 @@ CREATE TABLE IF NOT EXISTS system_scope ( icon VARCHAR(256), restricted BOOLEAN DEFAULT false NOT NULL, default_scope BOOLEAN DEFAULT false NOT NULL, - structured BOOLEAN DEFAULT false NOT NULL, - structured_param_description VARCHAR(256), UNIQUE (scope) ); diff --git a/openid-connect-server-webapp/src/main/resources/db/psql/scopes.sql b/openid-connect-server-webapp/src/main/resources/db/psql/scopes.sql index 8b2611b832..140c727554 100644 --- a/openid-connect-server-webapp/src/main/resources/db/psql/scopes.sql +++ b/openid-connect-server-webapp/src/main/resources/db/psql/scopes.sql @@ -10,20 +10,20 @@ START TRANSACTION; -- Insert scope information into the temporary tables. -- -INSERT INTO system_scope_TEMP (scope, description, icon, restricted, default_scope, structured, structured_param_description) VALUES - ('openid', 'log in using your identity', 'user', false, true, false, null), - ('profile', 'basic profile information', 'list-alt', false, true, false, null), - ('email', 'email address', 'envelope', false, true, false, null), - ('address', 'physical address', 'home', false, true, false, null), - ('phone', 'telephone number', 'bell', false, true, false, null), - ('offline_access', 'offline access', 'time', false, false, false, null); +INSERT INTO system_scope_TEMP (scope, description, icon, restricted, default_scope) VALUES + ('openid', 'log in using your identity', 'user', false, true), + ('profile', 'basic profile information', 'list-alt', false, true), + ('email', 'email address', 'envelope', false, true), + ('address', 'physical address', 'home', false, true), + ('phone', 'telephone number', 'bell', false, true), + ('offline_access', 'offline access', 'time', false, false); -- -- Merge the temporary scopes safely into the database. This is a two-step process to keep scopes from being created on every startup with a persistent store. -- -INSERT INTO system_scope (scope, description, icon, restricted, default_scope, structured, structured_param_description) - SELECT scope, description, icon, restricted, default_scope, structured, structured_param_description FROM system_scope_TEMP +INSERT INTO system_scope (scope, description, icon, restricted, default_scope) + SELECT scope, description, icon, restricted, default_scope FROM system_scope_TEMP ON CONFLICT(scope) DO NOTHING; From 676451c73d5fe247f7626e749b676abe54c648ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=84=AD=E8=84=88=E9=BE=8D?= Date: Thu, 21 Jun 2018 10:05:49 +0800 Subject: [PATCH 448/465] fix bug #1397 Attempting to execute an operation on a closed EntityManager. --- .../oauth2/repository/impl/JpaOAuth2TokenRepository.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java index 84267023c5..718a233572 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java @@ -190,7 +190,7 @@ public Set getAccessTokensByUserName(String name) { TypedQuery query = manager.createNamedQuery(OAuth2AccessTokenEntity.QUERY_BY_NAME, OAuth2AccessTokenEntity.class); query.setParameter(OAuth2AccessTokenEntity.PARAM_NAME, name); List results = query.getResultList(); - return results != null ? new HashSet<>(query.getResultList()) : new HashSet<>(); + return results != null ? new HashSet<>(results) : new HashSet<>(); } @Override @@ -198,7 +198,7 @@ public Set getRefreshTokensByUserName(String name) { TypedQuery query = manager.createNamedQuery(OAuth2RefreshTokenEntity.QUERY_BY_NAME, OAuth2RefreshTokenEntity.class); query.setParameter(OAuth2RefreshTokenEntity.PARAM_NAME, name); List results = query.getResultList(); - return results != null ? new HashSet<>(query.getResultList()) : new HashSet<>(); + return results != null ? new HashSet<>(results) : new HashSet<>(); } @Override From 4979f9f50eaddc22a1fb8f3adf9025439f82a955 Mon Sep 17 00:00:00 2001 From: Brady Mulhollem Date: Tue, 27 Nov 2018 16:06:38 -0500 Subject: [PATCH 449/465] #1435: Update guava dependency to latest version. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4a746a4253..580e4a5745 100644 --- a/pom.xml +++ b/pom.xml @@ -564,7 +564,7 @@ com.google.guava guava - 21.0 + 27.0-jre com.google.code.gson From 8430b42ab3e3ada9bc20d6fda1f4e1670749c27f Mon Sep 17 00:00:00 2001 From: Stephen Moore Date: Mon, 12 Nov 2018 09:48:50 -0500 Subject: [PATCH 450/465] Both approve pages were using pagecontext rather than the configured issuer --- .../src/main/webapp/WEB-INF/views/approve.jsp | 2 +- .../src/main/webapp/WEB-INF/views/approveDevice.jsp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/approve.jsp b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/approve.jsp index 4d3dda8ce7..6526fb8426 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/approve.jsp +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/approve.jsp @@ -37,7 +37,7 @@ + action="${ config.issuer }${ config.issuer.endsWith('/') ? '' : '/' }authorize" method="post">
diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/approveDevice.jsp b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/approveDevice.jsp index c49e1e8741..162170311e 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/approveDevice.jsp +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/views/approveDevice.jsp @@ -37,7 +37,7 @@ + action="${ config.issuer }${ config.issuer.endsWith('/') ? '' : '/' }device/approve" method="post">
From ad64aef0c58545a034cb855950d763495235efb3 Mon Sep 17 00:00:00 2001 From: Martin Kuba Date: Wed, 6 Mar 2019 11:35:05 +0100 Subject: [PATCH 451/465] updated dependencies patchlevels --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 580e4a5745..94d61d2c95 100644 --- a/pom.xml +++ b/pom.xml @@ -365,7 +365,7 @@ org.springframework spring-framework-bom - 4.3.7.RELEASE + 4.3.22.RELEASE pom import @@ -374,19 +374,19 @@ com.fasterxml.jackson.core jackson-databind - 2.9.0.pr2 + 2.9.8 com.fasterxml.jackson.core jackson-annotations - 2.9.0.pr2 + 2.9.8 org.springframework.security spring-security-bom - 4.2.4.RELEASE + 4.2.11.RELEASE pom import From ae7debba2f44f84ee638cab0ac8b35335c347ba2 Mon Sep 17 00:00:00 2001 From: Martin Kuba Date: Wed, 6 Mar 2019 11:14:52 +0100 Subject: [PATCH 452/465] added refresh_token into grant_types_supported --- .../main/java/org/mitre/discovery/web/DiscoveryEndpoint.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java b/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java index 47e9b20741..270a7649eb 100644 --- a/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java @@ -304,7 +304,7 @@ OPTIONAL. JSON array containing a list of the JWS signing algorithms (alg values JWSAlgorithm.ES256, JWSAlgorithm.ES384, JWSAlgorithm.ES512, JWSAlgorithm.PS256, JWSAlgorithm.PS384, JWSAlgorithm.PS512, Algorithm.NONE); - ArrayList grantTypes = Lists.newArrayList("authorization_code", "implicit", "urn:ietf:params:oauth:grant-type:jwt-bearer", "client_credentials", "urn:ietf:params:oauth:grant_type:redelegate", "urn:ietf:params:oauth:grant-type:device_code"); + ArrayList grantTypes = Lists.newArrayList("authorization_code", "implicit", "urn:ietf:params:oauth:grant-type:jwt-bearer", "client_credentials", "urn:ietf:params:oauth:grant_type:redelegate", "urn:ietf:params:oauth:grant-type:device_code","refresh_token"); Map m = new HashMap<>(); m.put("issuer", config.getIssuer()); From 5aa8b2a0a77baa937f3c9eaa757b25420e17a7ae Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 19 Apr 2019 16:00:06 -0400 Subject: [PATCH 453/465] updated changelog for release --- CHANGELOG.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5609bc7045..96c6356a0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ Unreleased: + +*1.3.3*: - Authorization codes are now longer - Client/RS can parse the "sub" and "user_id" claims in introspection response - Database-direct queries for fetching tokens by user (optimization) @@ -6,9 +8,12 @@ Unreleased: - Long scopes display properly and are still checkable - Language system remebers when it can't find a file and stops throwing so many errors - Index added for refresh tokens -- Updated to Spring Security 4.2.4 +- Updated to Spring Security 4.2.11 +- Updated Spring to 4.3.22 +- Change approve pages to use issuer instead of page context +- Updated oracle database scripts -*1.3.2: +*1.3.2*: - Added changelog - Set default redirect URI resolver strict matching to true - Fixed XSS vulnerability on redirect URI display on approval page From 73459f0348135013952146196d94e0d065f62739 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 19 Apr 2019 16:04:40 -0400 Subject: [PATCH 454/465] [maven-release-plugin] prepare release mitreid-connect-1.3.3 --- openid-connect-client/pom.xml | 2 +- openid-connect-common/pom.xml | 2 +- openid-connect-server-webapp/pom.xml | 2 +- openid-connect-server/pom.xml | 2 +- pom.xml | 2 +- uma-server-webapp/pom.xml | 2 +- uma-server/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/openid-connect-client/pom.xml b/openid-connect-client/pom.xml index 5e5bfae316..1612f52365 100644 --- a/openid-connect-client/pom.xml +++ b/openid-connect-client/pom.xml @@ -22,7 +22,7 @@ openid-connect-parent org.mitre - 1.3.3-SNAPSHOT + 1.3.3 .. openid-connect-client diff --git a/openid-connect-common/pom.xml b/openid-connect-common/pom.xml index 0cc1c23f38..3c27e0a664 100644 --- a/openid-connect-common/pom.xml +++ b/openid-connect-common/pom.xml @@ -22,7 +22,7 @@ openid-connect-parent org.mitre - 1.3.3-SNAPSHOT + 1.3.3 .. openid-connect-common diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index 9a4c45bc3d..500eba9744 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -21,7 +21,7 @@ org.mitre openid-connect-parent - 1.3.3-SNAPSHOT + 1.3.3 openid-connect-server-webapp war diff --git a/openid-connect-server/pom.xml b/openid-connect-server/pom.xml index ff6c36d088..936ba73ab9 100644 --- a/openid-connect-server/pom.xml +++ b/openid-connect-server/pom.xml @@ -23,7 +23,7 @@ org.mitre openid-connect-parent - 1.3.3-SNAPSHOT + 1.3.3 .. diff --git a/pom.xml b/pom.xml index 94d61d2c95..c5fc592f1a 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.mitre openid-connect-parent - 1.3.3-SNAPSHOT + 1.3.3 MITREid Connect pom diff --git a/uma-server-webapp/pom.xml b/uma-server-webapp/pom.xml index 25bf84abd5..acf028d569 100644 --- a/uma-server-webapp/pom.xml +++ b/uma-server-webapp/pom.xml @@ -19,7 +19,7 @@ org.mitre openid-connect-parent - 1.3.3-SNAPSHOT + 1.3.3 .. uma-server-webapp diff --git a/uma-server/pom.xml b/uma-server/pom.xml index a1ffeb1a93..31d127d275 100644 --- a/uma-server/pom.xml +++ b/uma-server/pom.xml @@ -19,7 +19,7 @@ org.mitre openid-connect-parent - 1.3.3-SNAPSHOT + 1.3.3 .. uma-server From 621e86e62dfe83bffc51342f874a579381e7f2bd Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Fri, 19 Apr 2019 16:04:45 -0400 Subject: [PATCH 455/465] [maven-release-plugin] prepare for next development iteration --- openid-connect-client/pom.xml | 2 +- openid-connect-common/pom.xml | 2 +- openid-connect-server-webapp/pom.xml | 2 +- openid-connect-server/pom.xml | 2 +- pom.xml | 2 +- uma-server-webapp/pom.xml | 2 +- uma-server/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/openid-connect-client/pom.xml b/openid-connect-client/pom.xml index 1612f52365..b891d4e0e6 100644 --- a/openid-connect-client/pom.xml +++ b/openid-connect-client/pom.xml @@ -22,7 +22,7 @@ openid-connect-parent org.mitre - 1.3.3 + 1.3.4-SNAPSHOT .. openid-connect-client diff --git a/openid-connect-common/pom.xml b/openid-connect-common/pom.xml index 3c27e0a664..a2b88b5179 100644 --- a/openid-connect-common/pom.xml +++ b/openid-connect-common/pom.xml @@ -22,7 +22,7 @@ openid-connect-parent org.mitre - 1.3.3 + 1.3.4-SNAPSHOT .. openid-connect-common diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index 500eba9744..11881547f7 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -21,7 +21,7 @@ org.mitre openid-connect-parent - 1.3.3 + 1.3.4-SNAPSHOT openid-connect-server-webapp war diff --git a/openid-connect-server/pom.xml b/openid-connect-server/pom.xml index 936ba73ab9..84fe62198e 100644 --- a/openid-connect-server/pom.xml +++ b/openid-connect-server/pom.xml @@ -23,7 +23,7 @@ org.mitre openid-connect-parent - 1.3.3 + 1.3.4-SNAPSHOT .. diff --git a/pom.xml b/pom.xml index c5fc592f1a..4ebd49e5a7 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.mitre openid-connect-parent - 1.3.3 + 1.3.4-SNAPSHOT MITREid Connect pom diff --git a/uma-server-webapp/pom.xml b/uma-server-webapp/pom.xml index acf028d569..e0485e03a5 100644 --- a/uma-server-webapp/pom.xml +++ b/uma-server-webapp/pom.xml @@ -19,7 +19,7 @@ org.mitre openid-connect-parent - 1.3.3 + 1.3.4-SNAPSHOT .. uma-server-webapp diff --git a/uma-server/pom.xml b/uma-server/pom.xml index 31d127d275..2373d34c1c 100644 --- a/uma-server/pom.xml +++ b/uma-server/pom.xml @@ -19,7 +19,7 @@ org.mitre openid-connect-parent - 1.3.3 + 1.3.4-SNAPSHOT .. uma-server From cc6bd4b5900bb14fef56f2bd212af2e8d8a5809b Mon Sep 17 00:00:00 2001 From: ruslan Date: Wed, 10 Apr 2019 17:13:20 +0300 Subject: [PATCH 456/465] upgrade eclipselink to v. 2.7.4 --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 4ebd49e5a7..6824f13603 100644 --- a/pom.xml +++ b/pom.xml @@ -439,12 +439,12 @@ org.eclipse.persistence org.eclipse.persistence.jpa - 2.5.1 + 2.7.4 org.eclipse.persistence javax.persistence - 2.1.1 + 2.2.1 com.zaxxer @@ -595,7 +595,7 @@ org.eclipse.persistence org.eclipse.persistence.core - 2.5.1 + 2.7.4 org.apache.commons From 0d4ef2cb4f77bea5df9e2d4f1cfff4dffb7045c0 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Thu, 1 Aug 2019 16:41:55 -0400 Subject: [PATCH 457/465] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index febfbd6737..610579f550 100644 --- a/README.md +++ b/README.md @@ -28,4 +28,4 @@ The authors and key contributors of the project include: * [Mark Janssen](https://github.com/praseodym) -Copyright ©2018, [MIT Internet Trust Consortium](http://www.trust.mit.edu/). Licensed under the Apache 2.0 license, for details see `LICENSE.txt`. +Licensed under the Apache 2.0 license, for details see `LICENSE.txt`. From 7eba3c12fed82388f917e8dd9b73e86e3a311e4c Mon Sep 17 00:00:00 2001 From: Michael Stepankin Date: Fri, 12 Feb 2021 15:22:12 +0000 Subject: [PATCH 458/465] Fix Spring Autobinding vulnerability 1. Make authorizationRequest no longer affected by http request parameters due to @ModelAttribute. See http://agrrrdog.blogspot.com/2017/03/autobinding-vulns-and-spring-mvc.html --- .../org/mitre/oauth2/web/OAuthConfirmationController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java index d89464690c..29c9a1419e 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java @@ -103,9 +103,9 @@ public OAuthConfirmationController(ClientDetailsEntityService clientService) { @PreAuthorize("hasRole('ROLE_USER')") @RequestMapping("/oauth/confirm_access") - public String confimAccess(Map model, @ModelAttribute("authorizationRequest") AuthorizationRequest authRequest, - Principal p) { + public String confirmAccess(Map model, Principal p) { + AuthorizationRequest authRequest = (AuthorizationRequest) model.get("authorizationRequest"); // Check the "prompt" parameter to see if we need to do special processing String prompt = (String)authRequest.getExtensions().get(PROMPT); From 6906f616e2b6962c6a5179df2e79f5b2c31880ab Mon Sep 17 00:00:00 2001 From: shrexster42 Date: Sat, 18 Dec 2021 22:30:43 +0000 Subject: [PATCH 459/465] Upgrade to Java 11 and Spring 5 --- openid-connect-common/pom.xml | 20 +++++++ .../UriEncodedClientUserDetailsService.java | 2 +- .../webapp/WEB-INF/application-context.xml | 22 ++++--- .../main/webapp/WEB-INF/assertion-config.xml | 10 ++-- .../src/main/webapp/WEB-INF/authz-config.xml | 10 ++-- .../src/main/webapp/WEB-INF/crypto-config.xml | 10 ++-- .../src/main/webapp/WEB-INF/data-context.xml | 4 +- .../main/webapp/WEB-INF/endpoint-config.xml | 10 ++-- .../src/main/webapp/WEB-INF/jpa-config.xml | 10 ++-- .../src/main/webapp/WEB-INF/local-config.xml | 10 ++-- .../src/main/webapp/WEB-INF/server-config.xml | 10 ++-- .../main/webapp/WEB-INF/spring-servlet.xml | 10 ++-- .../src/main/webapp/WEB-INF/task-config.xml | 4 +- .../src/main/webapp/WEB-INF/ui-config.xml | 10 ++-- .../src/main/webapp/WEB-INF/user-context.xml | 11 ++-- .../DynamicClientRegistrationEndpoint.java | 26 ++------- ...ProtectedResourceRegistrationEndpoint.java | 33 +++-------- .../impl/TestMITREidDataService_1_0.java | 40 ++++++------- .../impl/TestMITREidDataService_1_1.java | 40 ++++++------- .../impl/TestMITREidDataService_1_2.java | 40 ++++++------- .../impl/TestMITREidDataService_1_3.java | 58 +++++++++---------- pom.xml | 41 ++++++++++--- 22 files changed, 228 insertions(+), 203 deletions(-) diff --git a/openid-connect-common/pom.xml b/openid-connect-common/pom.xml index a2b88b5179..ebe5b462d9 100644 --- a/openid-connect-common/pom.xml +++ b/openid-connect-common/pom.xml @@ -87,6 +87,26 @@ org.bouncycastle bcprov-jdk15on + + javax.annotation + javax.annotation-api + + + jakarta.xml.bind + jakarta.xml.bind-api + + + javax.xml.bind + jaxb-api + + + javax.activation + activation + + + org.glassfish.jaxb + jaxb-runtime + jar diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/service/impl/UriEncodedClientUserDetailsService.java b/openid-connect-common/src/main/java/org/mitre/oauth2/service/impl/UriEncodedClientUserDetailsService.java index 335efbf184..64ef7e45cf 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/service/impl/UriEncodedClientUserDetailsService.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/service/impl/UriEncodedClientUserDetailsService.java @@ -91,7 +91,7 @@ public UserDetails loadUserByUsername(String clientId) throws UsernameNotFoundE } else { throw new UsernameNotFoundException("Client not found: " + clientId); } - } catch (UnsupportedEncodingException | InvalidClientException e) { + } catch (InvalidClientException e) { throw new UsernameNotFoundException("Client not found: " + clientId); } diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/application-context.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/application-context.xml index 480b5780ca..fdbc37ba72 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/application-context.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/application-context.xml @@ -25,12 +25,12 @@ xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd - http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.2.xsd - http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd - http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd - http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd - http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> + http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> @@ -246,9 +246,15 @@ + + - - + + + + + + diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/assertion-config.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/assertion-config.xml index 0ec4ce7f68..59ea49fe90 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/assertion-config.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/assertion-config.xml @@ -22,11 +22,11 @@ xmlns:security="http://www.springframework.org/schema/security" xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd - http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.2.xsd - http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd - http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd - http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> + http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/authz-config.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/authz-config.xml index 3b7a4faa87..0c5e5019f8 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/authz-config.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/authz-config.xml @@ -22,11 +22,11 @@ xmlns:security="http://www.springframework.org/schema/security" xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd - http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.2.xsd - http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd - http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd - http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> + http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> + http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/data-context.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/data-context.xml index 67d8bd146b..0313b5b1b5 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/data-context.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/data-context.xml @@ -19,8 +19,8 @@ + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd"> diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/endpoint-config.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/endpoint-config.xml index 14fbcf2ea7..bcfc14a6c3 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/endpoint-config.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/endpoint-config.xml @@ -22,11 +22,11 @@ xmlns:security="http://www.springframework.org/schema/security" xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd - http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.2.xsd - http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd - http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd - http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> + http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/jpa-config.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/jpa-config.xml index 592d56a2e9..afe40844af 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/jpa-config.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/jpa-config.xml @@ -22,11 +22,11 @@ xmlns:security="http://www.springframework.org/schema/security" xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd - http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.2.xsd - http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd - http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd - http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> + http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/local-config.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/local-config.xml index 3e5fef8e8a..e580f6e52a 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/local-config.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/local-config.xml @@ -24,11 +24,11 @@ xmlns:security="http://www.springframework.org/schema/security" xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd - http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.2.xsd - http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd - http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd - http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> + http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/server-config.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/server-config.xml index 544f01c98b..bf9f998652 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/server-config.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/server-config.xml @@ -24,11 +24,11 @@ xmlns:security="http://www.springframework.org/schema/security" xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd - http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.2.xsd - http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd - http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd - http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> + http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/spring-servlet.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/spring-servlet.xml index 9306834d02..f37e980ba6 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/spring-servlet.xml @@ -24,11 +24,11 @@ xmlns:security="http://www.springframework.org/schema/security" xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd - http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.2.xsd - http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd - http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd - http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> + http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/task-config.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/task-config.xml index 2b75133281..30f3e98a9a 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/task-config.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/task-config.xml @@ -19,8 +19,8 @@ + xsi:schemaLocation="http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/ui-config.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/ui-config.xml index 99951d2306..2e0cf646bb 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/ui-config.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/ui-config.xml @@ -22,11 +22,11 @@ xmlns:security="http://www.springframework.org/schema/security" xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd - http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.2.xsd - http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd - http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd - http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> + http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/user-context.xml b/openid-connect-server-webapp/src/main/webapp/WEB-INF/user-context.xml index 2aff943637..1bd665d398 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/user-context.xml +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/user-context.xml @@ -24,15 +24,16 @@ xmlns:security="http://www.springframework.org/schema/security" xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd - http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.2.xsd - http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd - http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd - http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> + http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> + diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java index a96f8209ea..79ea68116c 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/DynamicClientRegistrationEndpoint.java @@ -246,10 +246,6 @@ public String registerNewClient(@RequestBody String jsonString, Model m) { m.addAttribute(HttpCodeView.CODE, HttpStatus.CREATED); // http 201 return ClientInformationResponseView.VIEWNAME; - } catch (UnsupportedEncodingException e) { - logger.error("Unsupported encoding", e); - m.addAttribute(HttpCodeView.CODE, HttpStatus.INTERNAL_SERVER_ERROR); - return HttpCodeView.VIEWNAME; } catch (IllegalArgumentException e) { logger.error("Couldn't save client", e); @@ -284,20 +280,14 @@ public String readClientConfiguration(@PathVariable("id") String clientId, Model if (client != null && client.getClientId().equals(auth.getOAuth2Request().getClientId())) { - try { - OAuth2AccessTokenEntity token = rotateRegistrationTokenIfNecessary(auth, client); - RegisteredClient registered = new RegisteredClient(client, token.getValue(), config.getIssuer() + "register/" + UriUtils.encodePathSegment(client.getClientId(), "UTF-8")); + OAuth2AccessTokenEntity token = rotateRegistrationTokenIfNecessary(auth, client); + RegisteredClient registered = new RegisteredClient(client, token.getValue(), config.getIssuer() + "register/" + UriUtils.encodePathSegment(client.getClientId(), "UTF-8")); - // send it all out to the view - m.addAttribute("client", registered); - m.addAttribute(HttpCodeView.CODE, HttpStatus.OK); // http 200 + // send it all out to the view + m.addAttribute("client", registered); + m.addAttribute(HttpCodeView.CODE, HttpStatus.OK); // http 200 - return ClientInformationResponseView.VIEWNAME; - } catch (UnsupportedEncodingException e) { - logger.error("Unsupported encoding", e); - m.addAttribute(HttpCodeView.CODE, HttpStatus.INTERNAL_SERVER_ERROR); - return HttpCodeView.VIEWNAME; - } + return ClientInformationResponseView.VIEWNAME; } else { // client mismatch @@ -382,10 +372,6 @@ public String updateClient(@PathVariable("id") String clientId, @RequestBody Str m.addAttribute(HttpCodeView.CODE, HttpStatus.OK); // http 200 return ClientInformationResponseView.VIEWNAME; - } catch (UnsupportedEncodingException e) { - logger.error("Unsupported encoding", e); - m.addAttribute(HttpCodeView.CODE, HttpStatus.INTERNAL_SERVER_ERROR); - return HttpCodeView.VIEWNAME; } catch (IllegalArgumentException e) { logger.error("Couldn't save client", e); diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ProtectedResourceRegistrationEndpoint.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ProtectedResourceRegistrationEndpoint.java index 9e2e89b336..5be40caa34 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ProtectedResourceRegistrationEndpoint.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ProtectedResourceRegistrationEndpoint.java @@ -177,10 +177,6 @@ public String registerNewProtectedResource(@RequestBody String jsonString, Model m.addAttribute(HttpCodeView.CODE, HttpStatus.CREATED); // http 201 return ClientInformationResponseView.VIEWNAME; - } catch (UnsupportedEncodingException e) { - logger.error("Unsupported encoding", e); - m.addAttribute(HttpCodeView.CODE, HttpStatus.INTERNAL_SERVER_ERROR); - return HttpCodeView.VIEWNAME; } catch (IllegalArgumentException e) { logger.error("Couldn't save client", e); @@ -231,25 +227,18 @@ public String readResourceConfiguration(@PathVariable("id") String clientId, Mod ClientDetailsEntity client = clientService.loadClientByClientId(clientId); if (client != null && client.getClientId().equals(auth.getOAuth2Request().getClientId())) { + + // possibly update the token + OAuth2AccessTokenEntity token = fetchValidRegistrationToken(auth, client); + RegisteredClient registered = new RegisteredClient(client, token.getValue(), config.getIssuer() + "resource/" + UriUtils.encodePathSegment(client.getClientId(), "UTF-8")); + // send it all out to the view + m.addAttribute("client", registered); + m.addAttribute(HttpCodeView.CODE, HttpStatus.OK); // http 200 - try { - // possibly update the token - OAuth2AccessTokenEntity token = fetchValidRegistrationToken(auth, client); - - RegisteredClient registered = new RegisteredClient(client, token.getValue(), config.getIssuer() + "resource/" + UriUtils.encodePathSegment(client.getClientId(), "UTF-8")); - - // send it all out to the view - m.addAttribute("client", registered); - m.addAttribute(HttpCodeView.CODE, HttpStatus.OK); // http 200 - - return ClientInformationResponseView.VIEWNAME; - } catch (UnsupportedEncodingException e) { - logger.error("Unsupported encoding", e); - m.addAttribute(HttpCodeView.CODE, HttpStatus.INTERNAL_SERVER_ERROR); - return HttpCodeView.VIEWNAME; - } + return ClientInformationResponseView.VIEWNAME; + } else { // client mismatch logger.error("readResourceConfiguration failed, client ID mismatch: " @@ -356,10 +345,6 @@ public String updateProtectedResource(@PathVariable("id") String clientId, @Requ m.addAttribute(HttpCodeView.CODE, HttpStatus.OK); // http 200 return ClientInformationResponseView.VIEWNAME; - } catch (UnsupportedEncodingException e) { - logger.error("Unsupported encoding", e); - m.addAttribute(HttpCodeView.CODE, HttpStatus.INTERNAL_SERVER_ERROR); - return HttpCodeView.VIEWNAME; } catch (IllegalArgumentException e) { logger.error("Couldn't save client", e); diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_0.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_0.java index 6d5e7ec7ca..74c275939f 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_0.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_0.java @@ -144,7 +144,7 @@ public int compare(OAuth2RefreshTokenEntity entity1, OAuth2RefreshTokenEntity en @Test public void testImportRefreshTokens() throws IOException, ParseException { - Date expirationDate1 = formatter.parse("2014-09-10T22:49:44.090+0000", Locale.ENGLISH); + Date expirationDate1 = formatter.parse("2014-09-10T22:49:44.090+00:00", Locale.ENGLISH); ClientDetailsEntity mockedClient1 = mock(ClientDetailsEntity.class); when(mockedClient1.getClientId()).thenReturn("mocked_client_1"); @@ -159,7 +159,7 @@ public void testImportRefreshTokens() throws IOException, ParseException { token1.setJwt(JWTParser.parse("eyJhbGciOiJub25lIn0.eyJqdGkiOiJmOTg4OWQyOS0xMTk1LTQ4ODEtODgwZC1lZjVlYzAwY2Y4NDIifQ.")); token1.setAuthenticationHolder(mockedAuthHolder1); - Date expirationDate2 = formatter.parse("2015-01-07T18:31:50.079+0000", Locale.ENGLISH); + Date expirationDate2 = formatter.parse("2015-01-07T18:31:50.079+00:00", Locale.ENGLISH); ClientDetailsEntity mockedClient2 = mock(ClientDetailsEntity.class); when(mockedClient2.getClientId()).thenReturn("mocked_client_2"); @@ -184,9 +184,9 @@ public void testImportRefreshTokens() throws IOException, ParseException { "\"" + MITREidDataService.AUTHENTICATIONHOLDERS + "\": [], " + "\"" + MITREidDataService.REFRESHTOKENS + "\": [" + - "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+0000\"," + "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+00:00\"," + "\"authenticationHolderId\":1,\"value\":\"eyJhbGciOiJub25lIn0.eyJqdGkiOiJmOTg4OWQyOS0xMTk1LTQ4ODEtODgwZC1lZjVlYzAwY2Y4NDIifQ.\"}," + - "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+0000\"," + "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+00:00\"," + "\"authenticationHolderId\":2,\"value\":\"eyJhbGciOiJub25lIn0.eyJqdGkiOiJlYmEyYjc3My0xNjAzLTRmNDAtOWQ3MS1hMGIxZDg1OWE2MDAifQ.\"}" + " ]" + @@ -261,7 +261,7 @@ public int compare(OAuth2AccessTokenEntity entity1, OAuth2AccessTokenEntity enti @Test public void testImportAccessTokens() throws IOException, ParseException { - Date expirationDate1 = formatter.parse("2014-09-10T22:49:44.090+0000", Locale.ENGLISH); + Date expirationDate1 = formatter.parse("2014-09-10T22:49:44.090+00:00", Locale.ENGLISH); ClientDetailsEntity mockedClient1 = mock(ClientDetailsEntity.class); when(mockedClient1.getClientId()).thenReturn("mocked_client_1"); @@ -278,7 +278,7 @@ public void testImportAccessTokens() throws IOException, ParseException { token1.setScope(ImmutableSet.of("id-token")); token1.setTokenType("Bearer"); - String expiration2 = "2015-01-07T18:31:50.079+0000"; + String expiration2 = "2015-01-07T18:31:50.079+00:00"; Date expirationDate2 = formatter.parse(expiration2, Locale.ENGLISH); ClientDetailsEntity mockedClient2 = mock(ClientDetailsEntity.class); @@ -310,10 +310,10 @@ public void testImportAccessTokens() throws IOException, ParseException { "\"" + MITREidDataService.AUTHENTICATIONHOLDERS + "\": [], " + "\"" + MITREidDataService.ACCESSTOKENS + "\": [" + - "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+0000\"," + "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+00:00\"," + "\"refreshTokenId\":null,\"idTokenId\":null,\"scope\":[\"id-token\"],\"type\":\"Bearer\"," + "\"authenticationHolderId\":1,\"value\":\"eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE0MTI3ODk5NjgsInN1YiI6IjkwMzQyLkFTREZKV0ZBIiwiYXRfaGFzaCI6InptTmt1QmNRSmNYQktNaVpFODZqY0EiLCJhdWQiOlsiY2xpZW50Il0sImlzcyI6Imh0dHA6XC9cL2xvY2FsaG9zdDo4MDgwXC9vcGVuaWQtY29ubmVjdC1zZXJ2ZXItd2ViYXBwXC8iLCJpYXQiOjE0MTI3ODkzNjh9.xkEJ9IMXpH7qybWXomfq9WOOlpGYnrvGPgey9UQ4GLzbQx7JC0XgJK83PmrmBZosvFPCmota7FzI_BtwoZLgAZfFiH6w3WIlxuogoH-TxmYbxEpTHoTsszZppkq9mNgOlArV4jrR9y3TPo4MovsH71dDhS_ck-CvAlJunHlqhs0\"}," + - "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+0000\"," + "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+00:00\"," + "\"refreshTokenId\":1,\"idTokenId\":1,\"scope\":[\"openid\",\"offline_access\",\"email\",\"profile\"],\"type\":\"Bearer\"," + "\"authenticationHolderId\":2,\"value\":\"eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE0MTI3OTI5NjgsImF1ZCI6WyJjbGllbnQiXSwiaXNzIjoiaHR0cDpcL1wvbG9jYWxob3N0OjgwODBcL29wZW5pZC1jb25uZWN0LXNlcnZlci13ZWJhcHBcLyIsImp0aSI6IjBmZGE5ZmRiLTYyYzItNGIzZS05OTdiLWU0M2VhMDUwMzNiOSIsImlhdCI6MTQxMjc4OTM2OH0.xgaVpRLYE5MzbgXfE0tZt823tjAm6Oh3_kdR1P2I9jRLR6gnTlBQFlYi3Y_0pWNnZSerbAE8Tn6SJHZ9k-curVG0-ByKichV7CNvgsE5X_2wpEaUzejvKf8eZ-BammRY-ie6yxSkAarcUGMvGGOLbkFcz5CtrBpZhfd75J49BIQ\"}" + @@ -576,8 +576,8 @@ public WhitelistedSite answer(InvocationOnMock invocation) throws Throwable { @Test public void testImportGrants() throws IOException, ParseException { - Date creationDate1 = formatter.parse("2014-09-10T22:49:44.090+0000", Locale.ENGLISH); - Date accessDate1 = formatter.parse("2014-09-10T23:49:44.090+0000", Locale.ENGLISH); + Date creationDate1 = formatter.parse("2014-09-10T22:49:44.090+00:00", Locale.ENGLISH); + Date accessDate1 = formatter.parse("2014-09-10T23:49:44.090+00:00", Locale.ENGLISH); OAuth2AccessTokenEntity mockToken1 = mock(OAuth2AccessTokenEntity.class); when(mockToken1.getId()).thenReturn(1L); @@ -591,9 +591,9 @@ public void testImportGrants() throws IOException, ParseException { site1.setAllowedScopes(ImmutableSet.of("openid", "phone")); when(mockToken1.getApprovedSite()).thenReturn(site1); - Date creationDate2 = formatter.parse("2014-09-11T18:49:44.090+0000", Locale.ENGLISH); - Date accessDate2 = formatter.parse("2014-09-11T20:49:44.090+0000", Locale.ENGLISH); - Date timeoutDate2 = formatter.parse("2014-10-01T20:49:44.090+0000", Locale.ENGLISH); + Date creationDate2 = formatter.parse("2014-09-11T18:49:44.090+00:00", Locale.ENGLISH); + Date accessDate2 = formatter.parse("2014-09-11T20:49:44.090+00:00", Locale.ENGLISH); + Date timeoutDate2 = formatter.parse("2014-10-01T20:49:44.090+00:00", Locale.ENGLISH); ApprovedSite site2 = new ApprovedSite(); site2.setId(2L); @@ -614,11 +614,11 @@ public void testImportGrants() throws IOException, ParseException { "\"" + MITREidDataService.AUTHENTICATIONHOLDERS + "\": [], " + "\"" + MITREidDataService.GRANTS + "\": [" + - "{\"id\":1,\"clientId\":\"foo\",\"creationDate\":\"2014-09-10T22:49:44.090+0000\",\"accessDate\":\"2014-09-10T23:49:44.090+0000\"," + "{\"id\":1,\"clientId\":\"foo\",\"creationDate\":\"2014-09-10T22:49:44.090+00:00\",\"accessDate\":\"2014-09-10T23:49:44.090+00:00\"," + "\"userId\":\"user1\",\"whitelistedSiteId\":null,\"allowedScopes\":[\"openid\",\"phone\"], \"whitelistedSiteId\":1," + "\"approvedAccessTokens\":[1]}," + - "{\"id\":2,\"clientId\":\"bar\",\"creationDate\":\"2014-09-11T18:49:44.090+0000\",\"accessDate\":\"2014-09-11T20:49:44.090+0000\"," - + "\"timeoutDate\":\"2014-10-01T20:49:44.090+0000\",\"userId\":\"user2\"," + "{\"id\":2,\"clientId\":\"bar\",\"creationDate\":\"2014-09-11T18:49:44.090+00:00\",\"accessDate\":\"2014-09-11T20:49:44.090+00:00\"," + + "\"timeoutDate\":\"2014-10-01T20:49:44.090+00:00\",\"userId\":\"user2\"," + "\"allowedScopes\":[\"openid\",\"offline_access\",\"email\",\"profile\"]}" + " ]" + @@ -831,7 +831,7 @@ public void testImportSystemScopes() throws IOException { @Test public void testFixRefreshTokenAuthHolderReferencesOnImport() throws IOException, ParseException { - String expiration1 = "2014-09-10T22:49:44.090+0000"; + String expiration1 = "2014-09-10T22:49:44.090+00:00"; Date expirationDate1 = formatter.parse(expiration1, Locale.ENGLISH); ClientDetailsEntity mockedClient1 = mock(ClientDetailsEntity.class); @@ -854,7 +854,7 @@ public void testFixRefreshTokenAuthHolderReferencesOnImport() throws IOException token1.setJwt(JWTParser.parse("eyJhbGciOiJub25lIn0.eyJqdGkiOiJmOTg4OWQyOS0xMTk1LTQ4ODEtODgwZC1lZjVlYzAwY2Y4NDIifQ.")); token1.setAuthenticationHolder(holder1); - String expiration2 = "2015-01-07T18:31:50.079+0000"; + String expiration2 = "2015-01-07T18:31:50.079+00:00"; Date expirationDate2 = formatter.parse(expiration2, Locale.ENGLISH); ClientDetailsEntity mockedClient2 = mock(ClientDetailsEntity.class); @@ -893,9 +893,9 @@ public void testFixRefreshTokenAuthHolderReferencesOnImport() throws IOException " ]," + "\"" + MITREidDataService.REFRESHTOKENS + "\": [" + - "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+0000\"," + "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+00:00\"," + "\"authenticationHolderId\":1,\"value\":\"eyJhbGciOiJub25lIn0.eyJqdGkiOiJmOTg4OWQyOS0xMTk1LTQ4ODEtODgwZC1lZjVlYzAwY2Y4NDIifQ.\"}," + - "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+0000\"," + "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+00:00\"," + "\"authenticationHolderId\":2,\"value\":\"eyJhbGciOiJub25lIn0.eyJqdGkiOiJlYmEyYjc3My0xNjAzLTRmNDAtOWQ3MS1hMGIxZDg1OWE2MDAifQ.\"}" + " ]" + diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_1.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_1.java index d7ab851fd4..cfeb43a6f7 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_1.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_1.java @@ -145,7 +145,7 @@ public int compare(OAuth2RefreshTokenEntity entity1, OAuth2RefreshTokenEntity en @Test public void testImportRefreshTokens() throws IOException, ParseException { - String expiration1 = "2014-09-10T22:49:44.090+0000"; + String expiration1 = "2014-09-10T22:49:44.090+00:00"; Date expirationDate1 = formatter.parse(expiration1, Locale.ENGLISH); ClientDetailsEntity mockedClient1 = mock(ClientDetailsEntity.class); @@ -161,7 +161,7 @@ public void testImportRefreshTokens() throws IOException, ParseException { token1.setJwt(JWTParser.parse("eyJhbGciOiJub25lIn0.eyJqdGkiOiJmOTg4OWQyOS0xMTk1LTQ4ODEtODgwZC1lZjVlYzAwY2Y4NDIifQ.")); token1.setAuthenticationHolder(mockedAuthHolder1); - String expiration2 = "2015-01-07T18:31:50.079+0000"; + String expiration2 = "2015-01-07T18:31:50.079+00:00"; Date expirationDate2 = formatter.parse(expiration2, Locale.ENGLISH); ClientDetailsEntity mockedClient2 = mock(ClientDetailsEntity.class); @@ -187,9 +187,9 @@ public void testImportRefreshTokens() throws IOException, ParseException { "\"" + MITREidDataService.AUTHENTICATIONHOLDERS + "\": [], " + "\"" + MITREidDataService.REFRESHTOKENS + "\": [" + - "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+0000\"," + "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+00:00\"," + "\"authenticationHolderId\":1,\"value\":\"eyJhbGciOiJub25lIn0.eyJqdGkiOiJmOTg4OWQyOS0xMTk1LTQ4ODEtODgwZC1lZjVlYzAwY2Y4NDIifQ.\"}," + - "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+0000\"," + "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+00:00\"," + "\"authenticationHolderId\":2,\"value\":\"eyJhbGciOiJub25lIn0.eyJqdGkiOiJlYmEyYjc3My0xNjAzLTRmNDAtOWQ3MS1hMGIxZDg1OWE2MDAifQ.\"}" + " ]" + @@ -264,7 +264,7 @@ public int compare(OAuth2AccessTokenEntity entity1, OAuth2AccessTokenEntity enti @Test public void testImportAccessTokens() throws IOException, ParseException { - String expiration1 = "2014-09-10T22:49:44.090+0000"; + String expiration1 = "2014-09-10T22:49:44.090+00:00"; Date expirationDate1 = formatter.parse(expiration1, Locale.ENGLISH); ClientDetailsEntity mockedClient1 = mock(ClientDetailsEntity.class); @@ -282,7 +282,7 @@ public void testImportAccessTokens() throws IOException, ParseException { token1.setScope(ImmutableSet.of("id-token")); token1.setTokenType("Bearer"); - String expiration2 = "2015-01-07T18:31:50.079+0000"; + String expiration2 = "2015-01-07T18:31:50.079+00:00"; Date expirationDate2 = formatter.parse(expiration2, Locale.ENGLISH); ClientDetailsEntity mockedClient2 = mock(ClientDetailsEntity.class); @@ -314,10 +314,10 @@ public void testImportAccessTokens() throws IOException, ParseException { "\"" + MITREidDataService.AUTHENTICATIONHOLDERS + "\": [], " + "\"" + MITREidDataService.ACCESSTOKENS + "\": [" + - "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+0000\"," + "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+00:00\"," + "\"refreshTokenId\":null,\"idTokenId\":null,\"scope\":[\"id-token\"],\"type\":\"Bearer\"," + "\"authenticationHolderId\":1,\"value\":\"eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE0MTI3ODk5NjgsInN1YiI6IjkwMzQyLkFTREZKV0ZBIiwiYXRfaGFzaCI6InptTmt1QmNRSmNYQktNaVpFODZqY0EiLCJhdWQiOlsiY2xpZW50Il0sImlzcyI6Imh0dHA6XC9cL2xvY2FsaG9zdDo4MDgwXC9vcGVuaWQtY29ubmVjdC1zZXJ2ZXItd2ViYXBwXC8iLCJpYXQiOjE0MTI3ODkzNjh9.xkEJ9IMXpH7qybWXomfq9WOOlpGYnrvGPgey9UQ4GLzbQx7JC0XgJK83PmrmBZosvFPCmota7FzI_BtwoZLgAZfFiH6w3WIlxuogoH-TxmYbxEpTHoTsszZppkq9mNgOlArV4jrR9y3TPo4MovsH71dDhS_ck-CvAlJunHlqhs0\"}," + - "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+0000\"," + "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+00:00\"," + "\"refreshTokenId\":1,\"idTokenId\":1,\"scope\":[\"openid\",\"offline_access\",\"email\",\"profile\"],\"type\":\"Bearer\"," + "\"authenticationHolderId\":2,\"value\":\"eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE0MTI3OTI5NjgsImF1ZCI6WyJjbGllbnQiXSwiaXNzIjoiaHR0cDpcL1wvbG9jYWxob3N0OjgwODBcL29wZW5pZC1jb25uZWN0LXNlcnZlci13ZWJhcHBcLyIsImp0aSI6IjBmZGE5ZmRiLTYyYzItNGIzZS05OTdiLWU0M2VhMDUwMzNiOSIsImlhdCI6MTQxMjc4OTM2OH0.xgaVpRLYE5MzbgXfE0tZt823tjAm6Oh3_kdR1P2I9jRLR6gnTlBQFlYi3Y_0pWNnZSerbAE8Tn6SJHZ9k-curVG0-ByKichV7CNvgsE5X_2wpEaUzejvKf8eZ-BammRY-ie6yxSkAarcUGMvGGOLbkFcz5CtrBpZhfd75J49BIQ\"}" + @@ -579,8 +579,8 @@ public WhitelistedSite answer(InvocationOnMock invocation) throws Throwable { @Test public void testImportGrants() throws IOException, ParseException { - Date creationDate1 = formatter.parse("2014-09-10T22:49:44.090+0000", Locale.ENGLISH); - Date accessDate1 = formatter.parse("2014-09-10T23:49:44.090+0000", Locale.ENGLISH); + Date creationDate1 = formatter.parse("2014-09-10T22:49:44.090+00:00", Locale.ENGLISH); + Date accessDate1 = formatter.parse("2014-09-10T23:49:44.090+00:00", Locale.ENGLISH); OAuth2AccessTokenEntity mockToken1 = mock(OAuth2AccessTokenEntity.class); when(mockToken1.getId()).thenReturn(1L); @@ -594,9 +594,9 @@ public void testImportGrants() throws IOException, ParseException { site1.setAllowedScopes(ImmutableSet.of("openid", "phone")); when(mockToken1.getApprovedSite()).thenReturn(site1); - Date creationDate2 = formatter.parse("2014-09-11T18:49:44.090+0000", Locale.ENGLISH); - Date accessDate2 = formatter.parse("2014-09-11T20:49:44.090+0000", Locale.ENGLISH); - Date timeoutDate2 = formatter.parse("2014-10-01T20:49:44.090+0000", Locale.ENGLISH); + Date creationDate2 = formatter.parse("2014-09-11T18:49:44.090+00:00", Locale.ENGLISH); + Date accessDate2 = formatter.parse("2014-09-11T20:49:44.090+00:00", Locale.ENGLISH); + Date timeoutDate2 = formatter.parse("2014-10-01T20:49:44.090+00:00", Locale.ENGLISH); ApprovedSite site2 = new ApprovedSite(); site2.setId(2L); @@ -617,11 +617,11 @@ public void testImportGrants() throws IOException, ParseException { "\"" + MITREidDataService.AUTHENTICATIONHOLDERS + "\": [], " + "\"" + MITREidDataService.GRANTS + "\": [" + - "{\"id\":1,\"clientId\":\"foo\",\"creationDate\":\"2014-09-10T22:49:44.090+0000\",\"accessDate\":\"2014-09-10T23:49:44.090+0000\"," + "{\"id\":1,\"clientId\":\"foo\",\"creationDate\":\"2014-09-10T22:49:44.090+00:00\",\"accessDate\":\"2014-09-10T23:49:44.090+00:00\"," + "\"userId\":\"user1\",\"whitelistedSiteId\":null,\"allowedScopes\":[\"openid\",\"phone\"], \"whitelistedSiteId\":1," + "\"approvedAccessTokens\":[1]}," + - "{\"id\":2,\"clientId\":\"bar\",\"creationDate\":\"2014-09-11T18:49:44.090+0000\",\"accessDate\":\"2014-09-11T20:49:44.090+0000\"," - + "\"timeoutDate\":\"2014-10-01T20:49:44.090+0000\",\"userId\":\"user2\"," + "{\"id\":2,\"clientId\":\"bar\",\"creationDate\":\"2014-09-11T18:49:44.090+00:00\",\"accessDate\":\"2014-09-11T20:49:44.090+00:00\"," + + "\"timeoutDate\":\"2014-10-01T20:49:44.090+00:00\",\"userId\":\"user2\"," + "\"allowedScopes\":[\"openid\",\"offline_access\",\"email\",\"profile\"]}" + " ]" + @@ -833,7 +833,7 @@ public void testImportSystemScopes() throws IOException { @Test public void testFixRefreshTokenAuthHolderReferencesOnImport() throws IOException, ParseException { - String expiration1 = "2014-09-10T22:49:44.090+0000"; + String expiration1 = "2014-09-10T22:49:44.090+00:00"; Date expirationDate1 = formatter.parse(expiration1, Locale.ENGLISH); ClientDetailsEntity mockedClient1 = mock(ClientDetailsEntity.class); @@ -856,7 +856,7 @@ public void testFixRefreshTokenAuthHolderReferencesOnImport() throws IOException token1.setJwt(JWTParser.parse("eyJhbGciOiJub25lIn0.eyJqdGkiOiJmOTg4OWQyOS0xMTk1LTQ4ODEtODgwZC1lZjVlYzAwY2Y4NDIifQ.")); token1.setAuthenticationHolder(holder1); - String expiration2 = "2015-01-07T18:31:50.079+0000"; + String expiration2 = "2015-01-07T18:31:50.079+00:00"; Date expirationDate2 = formatter.parse(expiration2, Locale.ENGLISH); ClientDetailsEntity mockedClient2 = mock(ClientDetailsEntity.class); @@ -895,9 +895,9 @@ public void testFixRefreshTokenAuthHolderReferencesOnImport() throws IOException " ]," + "\"" + MITREidDataService.REFRESHTOKENS + "\": [" + - "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+0000\"," + "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+00:00\"," + "\"authenticationHolderId\":1,\"value\":\"eyJhbGciOiJub25lIn0.eyJqdGkiOiJmOTg4OWQyOS0xMTk1LTQ4ODEtODgwZC1lZjVlYzAwY2Y4NDIifQ.\"}," + - "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+0000\"," + "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+00:00\"," + "\"authenticationHolderId\":2,\"value\":\"eyJhbGciOiJub25lIn0.eyJqdGkiOiJlYmEyYjc3My0xNjAzLTRmNDAtOWQ3MS1hMGIxZDg1OWE2MDAifQ.\"}" + " ]" + diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_2.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_2.java index 594900ae29..598471126f 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_2.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_2.java @@ -147,7 +147,7 @@ public int compare(OAuth2RefreshTokenEntity entity1, OAuth2RefreshTokenEntity en @Test public void testImportRefreshTokens() throws IOException, ParseException { - String expiration1 = "2014-09-10T22:49:44.090+0000"; + String expiration1 = "2014-09-10T22:49:44.090+00:00"; Date expirationDate1 = formatter.parse(expiration1, Locale.ENGLISH); ClientDetailsEntity mockedClient1 = mock(ClientDetailsEntity.class); @@ -163,7 +163,7 @@ public void testImportRefreshTokens() throws IOException, ParseException { token1.setJwt(JWTParser.parse("eyJhbGciOiJub25lIn0.eyJqdGkiOiJmOTg4OWQyOS0xMTk1LTQ4ODEtODgwZC1lZjVlYzAwY2Y4NDIifQ.")); token1.setAuthenticationHolder(mockedAuthHolder1); - String expiration2 = "2015-01-07T18:31:50.079+0000"; + String expiration2 = "2015-01-07T18:31:50.079+00:00"; Date expirationDate2 = formatter.parse(expiration2, Locale.ENGLISH); ClientDetailsEntity mockedClient2 = mock(ClientDetailsEntity.class); @@ -189,9 +189,9 @@ public void testImportRefreshTokens() throws IOException, ParseException { "\"" + MITREidDataService.AUTHENTICATIONHOLDERS + "\": [], " + "\"" + MITREidDataService.REFRESHTOKENS + "\": [" + - "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+0000\"," + "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+00:00\"," + "\"authenticationHolderId\":1,\"value\":\"eyJhbGciOiJub25lIn0.eyJqdGkiOiJmOTg4OWQyOS0xMTk1LTQ4ODEtODgwZC1lZjVlYzAwY2Y4NDIifQ.\"}," + - "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+0000\"," + "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+00:00\"," + "\"authenticationHolderId\":2,\"value\":\"eyJhbGciOiJub25lIn0.eyJqdGkiOiJlYmEyYjc3My0xNjAzLTRmNDAtOWQ3MS1hMGIxZDg1OWE2MDAifQ.\"}" + " ]" + @@ -266,7 +266,7 @@ public int compare(OAuth2AccessTokenEntity entity1, OAuth2AccessTokenEntity enti @Test public void testImportAccessTokens() throws IOException, ParseException { - String expiration1 = "2014-09-10T22:49:44.090+0000"; + String expiration1 = "2014-09-10T22:49:44.090+00:00"; Date expirationDate1 = formatter.parse(expiration1, Locale.ENGLISH); ClientDetailsEntity mockedClient1 = mock(ClientDetailsEntity.class); @@ -284,7 +284,7 @@ public void testImportAccessTokens() throws IOException, ParseException { token1.setScope(ImmutableSet.of("id-token")); token1.setTokenType("Bearer"); - String expiration2 = "2015-01-07T18:31:50.079+0000"; + String expiration2 = "2015-01-07T18:31:50.079+00:00"; Date expirationDate2 = formatter.parse(expiration2, Locale.ENGLISH); ClientDetailsEntity mockedClient2 = mock(ClientDetailsEntity.class); @@ -316,10 +316,10 @@ public void testImportAccessTokens() throws IOException, ParseException { "\"" + MITREidDataService.AUTHENTICATIONHOLDERS + "\": [], " + "\"" + MITREidDataService.ACCESSTOKENS + "\": [" + - "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+0000\"," + "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+00:00\"," + "\"refreshTokenId\":null,\"idTokenId\":null,\"scope\":[\"id-token\"],\"type\":\"Bearer\"," + "\"authenticationHolderId\":1,\"value\":\"eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE0MTI3ODk5NjgsInN1YiI6IjkwMzQyLkFTREZKV0ZBIiwiYXRfaGFzaCI6InptTmt1QmNRSmNYQktNaVpFODZqY0EiLCJhdWQiOlsiY2xpZW50Il0sImlzcyI6Imh0dHA6XC9cL2xvY2FsaG9zdDo4MDgwXC9vcGVuaWQtY29ubmVjdC1zZXJ2ZXItd2ViYXBwXC8iLCJpYXQiOjE0MTI3ODkzNjh9.xkEJ9IMXpH7qybWXomfq9WOOlpGYnrvGPgey9UQ4GLzbQx7JC0XgJK83PmrmBZosvFPCmota7FzI_BtwoZLgAZfFiH6w3WIlxuogoH-TxmYbxEpTHoTsszZppkq9mNgOlArV4jrR9y3TPo4MovsH71dDhS_ck-CvAlJunHlqhs0\"}," + - "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+0000\"," + "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+00:00\"," + "\"refreshTokenId\":1,\"idTokenId\":1,\"scope\":[\"openid\",\"offline_access\",\"email\",\"profile\"],\"type\":\"Bearer\"," + "\"authenticationHolderId\":2,\"value\":\"eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE0MTI3OTI5NjgsImF1ZCI6WyJjbGllbnQiXSwiaXNzIjoiaHR0cDpcL1wvbG9jYWxob3N0OjgwODBcL29wZW5pZC1jb25uZWN0LXNlcnZlci13ZWJhcHBcLyIsImp0aSI6IjBmZGE5ZmRiLTYyYzItNGIzZS05OTdiLWU0M2VhMDUwMzNiOSIsImlhdCI6MTQxMjc4OTM2OH0.xgaVpRLYE5MzbgXfE0tZt823tjAm6Oh3_kdR1P2I9jRLR6gnTlBQFlYi3Y_0pWNnZSerbAE8Tn6SJHZ9k-curVG0-ByKichV7CNvgsE5X_2wpEaUzejvKf8eZ-BammRY-ie6yxSkAarcUGMvGGOLbkFcz5CtrBpZhfd75J49BIQ\"}" + @@ -581,8 +581,8 @@ public WhitelistedSite answer(InvocationOnMock invocation) throws Throwable { @Test public void testImportGrants() throws IOException, ParseException { - Date creationDate1 = formatter.parse("2014-09-10T22:49:44.090+0000", Locale.ENGLISH); - Date accessDate1 = formatter.parse("2014-09-10T23:49:44.090+0000", Locale.ENGLISH); + Date creationDate1 = formatter.parse("2014-09-10T22:49:44.090+00:00", Locale.ENGLISH); + Date accessDate1 = formatter.parse("2014-09-10T23:49:44.090+00:00", Locale.ENGLISH); OAuth2AccessTokenEntity mockToken1 = mock(OAuth2AccessTokenEntity.class); when(mockToken1.getId()).thenReturn(1L); @@ -596,9 +596,9 @@ public void testImportGrants() throws IOException, ParseException { site1.setAllowedScopes(ImmutableSet.of("openid", "phone")); when(mockToken1.getApprovedSite()).thenReturn(site1); - Date creationDate2 = formatter.parse("2014-09-11T18:49:44.090+0000", Locale.ENGLISH); - Date accessDate2 = formatter.parse("2014-09-11T20:49:44.090+0000", Locale.ENGLISH); - Date timeoutDate2 = formatter.parse("2014-10-01T20:49:44.090+0000", Locale.ENGLISH); + Date creationDate2 = formatter.parse("2014-09-11T18:49:44.090+00:00", Locale.ENGLISH); + Date accessDate2 = formatter.parse("2014-09-11T20:49:44.090+00:00", Locale.ENGLISH); + Date timeoutDate2 = formatter.parse("2014-10-01T20:49:44.090+00:00", Locale.ENGLISH); ApprovedSite site2 = new ApprovedSite(); site2.setId(2L); @@ -619,11 +619,11 @@ public void testImportGrants() throws IOException, ParseException { "\"" + MITREidDataService.AUTHENTICATIONHOLDERS + "\": [], " + "\"" + MITREidDataService.GRANTS + "\": [" + - "{\"id\":1,\"clientId\":\"foo\",\"creationDate\":\"2014-09-10T22:49:44.090+0000\",\"accessDate\":\"2014-09-10T23:49:44.090+0000\"," + "{\"id\":1,\"clientId\":\"foo\",\"creationDate\":\"2014-09-10T22:49:44.090+00:00\",\"accessDate\":\"2014-09-10T23:49:44.090+00:00\"," + "\"userId\":\"user1\",\"whitelistedSiteId\":null,\"allowedScopes\":[\"openid\",\"phone\"], \"whitelistedSiteId\":1," + "\"approvedAccessTokens\":[1]}," + - "{\"id\":2,\"clientId\":\"bar\",\"creationDate\":\"2014-09-11T18:49:44.090+0000\",\"accessDate\":\"2014-09-11T20:49:44.090+0000\"," - + "\"timeoutDate\":\"2014-10-01T20:49:44.090+0000\",\"userId\":\"user2\"," + "{\"id\":2,\"clientId\":\"bar\",\"creationDate\":\"2014-09-11T18:49:44.090+00:00\",\"accessDate\":\"2014-09-11T20:49:44.090+00:00\"," + + "\"timeoutDate\":\"2014-10-01T20:49:44.090+00:00\",\"userId\":\"user2\"," + "\"allowedScopes\":[\"openid\",\"offline_access\",\"email\",\"profile\"]}" + " ]" + @@ -835,7 +835,7 @@ public void testImportSystemScopes() throws IOException { @Test public void testFixRefreshTokenAuthHolderReferencesOnImport() throws IOException, ParseException { - String expiration1 = "2014-09-10T22:49:44.090+0000"; + String expiration1 = "2014-09-10T22:49:44.090+00:00"; Date expirationDate1 = formatter.parse(expiration1, Locale.ENGLISH); ClientDetailsEntity mockedClient1 = mock(ClientDetailsEntity.class); @@ -858,7 +858,7 @@ public void testFixRefreshTokenAuthHolderReferencesOnImport() throws IOException token1.setJwt(JWTParser.parse("eyJhbGciOiJub25lIn0.eyJqdGkiOiJmOTg4OWQyOS0xMTk1LTQ4ODEtODgwZC1lZjVlYzAwY2Y4NDIifQ.")); token1.setAuthenticationHolder(holder1); - String expiration2 = "2015-01-07T18:31:50.079+0000"; + String expiration2 = "2015-01-07T18:31:50.079+00:00"; Date expirationDate2 = formatter.parse(expiration2, Locale.ENGLISH); ClientDetailsEntity mockedClient2 = mock(ClientDetailsEntity.class); @@ -897,9 +897,9 @@ public void testFixRefreshTokenAuthHolderReferencesOnImport() throws IOException " ]," + "\"" + MITREidDataService.REFRESHTOKENS + "\": [" + - "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+0000\"," + "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+00:00\"," + "\"authenticationHolderId\":1,\"value\":\"eyJhbGciOiJub25lIn0.eyJqdGkiOiJmOTg4OWQyOS0xMTk1LTQ4ODEtODgwZC1lZjVlYzAwY2Y4NDIifQ.\"}," + - "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+0000\"," + "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+00:00\"," + "\"authenticationHolderId\":2,\"value\":\"eyJhbGciOiJub25lIn0.eyJqdGkiOiJlYmEyYjc3My0xNjAzLTRmNDAtOWQ3MS1hMGIxZDg1OWE2MDAifQ.\"}" + " ]" + diff --git a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_3.java b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_3.java index 29a04d932d..19a12c2350 100644 --- a/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_3.java +++ b/openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_3.java @@ -150,7 +150,7 @@ public void prepare() { @Test public void testExportRefreshTokens() throws IOException, ParseException { - String expiration1 = "2014-09-10T22:49:44.090+0000"; + String expiration1 = "2014-09-10T22:49:44.090+00:00"; Date expirationDate1 = formatter.parse(expiration1, Locale.ENGLISH); ClientDetailsEntity mockedClient1 = mock(ClientDetailsEntity.class); @@ -166,7 +166,7 @@ public void testExportRefreshTokens() throws IOException, ParseException { token1.setJwt(JWTParser.parse("eyJhbGciOiJub25lIn0.eyJqdGkiOiJmOTg4OWQyOS0xMTk1LTQ4ODEtODgwZC1lZjVlYzAwY2Y4NDIifQ.")); token1.setAuthenticationHolder(mockedAuthHolder1); - String expiration2 = "2015-01-07T18:31:50.079+0000"; + String expiration2 = "2015-01-07T18:31:50.079+00:00"; Date expirationDate2 = formatter.parse(expiration2, Locale.ENGLISH); ClientDetailsEntity mockedClient2 = mock(ClientDetailsEntity.class); @@ -273,7 +273,7 @@ public int compare(OAuth2RefreshTokenEntity entity1, OAuth2RefreshTokenEntity en @Test public void testImportRefreshTokens() throws IOException, ParseException { - String expiration1 = "2014-09-10T22:49:44.090+0000"; + String expiration1 = "2014-09-10T22:49:44.090+00:00"; Date expirationDate1 = formatter.parse(expiration1, Locale.ENGLISH); ClientDetailsEntity mockedClient1 = mock(ClientDetailsEntity.class); @@ -289,7 +289,7 @@ public void testImportRefreshTokens() throws IOException, ParseException { token1.setJwt(JWTParser.parse("eyJhbGciOiJub25lIn0.eyJqdGkiOiJmOTg4OWQyOS0xMTk1LTQ4ODEtODgwZC1lZjVlYzAwY2Y4NDIifQ.")); token1.setAuthenticationHolder(mockedAuthHolder1); - String expiration2 = "2015-01-07T18:31:50.079+0000"; + String expiration2 = "2015-01-07T18:31:50.079+00:00"; Date expirationDate2 = formatter.parse(expiration2, Locale.ENGLISH); ClientDetailsEntity mockedClient2 = mock(ClientDetailsEntity.class); @@ -315,9 +315,9 @@ public void testImportRefreshTokens() throws IOException, ParseException { "\"" + MITREidDataService.AUTHENTICATIONHOLDERS + "\": [], " + "\"" + MITREidDataService.REFRESHTOKENS + "\": [" + - "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+0000\"," + "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+00:00\"," + "\"authenticationHolderId\":1,\"value\":\"eyJhbGciOiJub25lIn0.eyJqdGkiOiJmOTg4OWQyOS0xMTk1LTQ4ODEtODgwZC1lZjVlYzAwY2Y4NDIifQ.\"}," + - "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+0000\"," + "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+00:00\"," + "\"authenticationHolderId\":2,\"value\":\"eyJhbGciOiJub25lIn0.eyJqdGkiOiJlYmEyYjc3My0xNjAzLTRmNDAtOWQ3MS1hMGIxZDg1OWE2MDAifQ.\"}" + " ]" + @@ -385,7 +385,7 @@ public AuthenticationHolderEntity answer(InvocationOnMock invocation) throws Thr @Test public void testExportAccessTokens() throws IOException, ParseException { - String expiration1 = "2014-09-10T22:49:44.090+0000"; + String expiration1 = "2014-09-10T22:49:44.090+00:00"; Date expirationDate1 = formatter.parse(expiration1, Locale.ENGLISH); ClientDetailsEntity mockedClient1 = mock(ClientDetailsEntity.class); @@ -403,7 +403,7 @@ public void testExportAccessTokens() throws IOException, ParseException { token1.setScope(ImmutableSet.of("id-token")); token1.setTokenType("Bearer"); - String expiration2 = "2015-01-07T18:31:50.079+0000"; + String expiration2 = "2015-01-07T18:31:50.079+00:00"; Date expirationDate2 = formatter.parse(expiration2, Locale.ENGLISH); ClientDetailsEntity mockedClient2 = mock(ClientDetailsEntity.class); @@ -523,7 +523,7 @@ public int compare(OAuth2AccessTokenEntity entity1, OAuth2AccessTokenEntity enti @Test public void testImportAccessTokens() throws IOException, ParseException { - String expiration1 = "2014-09-10T22:49:44.090+0000"; + String expiration1 = "2014-09-10T22:49:44.090+00:00"; Date expirationDate1 = formatter.parse(expiration1, Locale.ENGLISH); ClientDetailsEntity mockedClient1 = mock(ClientDetailsEntity.class); @@ -541,7 +541,7 @@ public void testImportAccessTokens() throws IOException, ParseException { token1.setScope(ImmutableSet.of("id-token")); token1.setTokenType("Bearer"); - String expiration2 = "2015-01-07T18:31:50.079+0000"; + String expiration2 = "2015-01-07T18:31:50.079+00:00"; Date expirationDate2 = formatter.parse(expiration2, Locale.ENGLISH); ClientDetailsEntity mockedClient2 = mock(ClientDetailsEntity.class); @@ -573,10 +573,10 @@ public void testImportAccessTokens() throws IOException, ParseException { "\"" + MITREidDataService.AUTHENTICATIONHOLDERS + "\": [], " + "\"" + MITREidDataService.ACCESSTOKENS + "\": [" + - "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+0000\"," + "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+00:00\"," + "\"refreshTokenId\":null,\"idTokenId\":null,\"scope\":[\"id-token\"],\"type\":\"Bearer\"," + "\"authenticationHolderId\":1,\"value\":\"eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE0MTI3ODk5NjgsInN1YiI6IjkwMzQyLkFTREZKV0ZBIiwiYXRfaGFzaCI6InptTmt1QmNRSmNYQktNaVpFODZqY0EiLCJhdWQiOlsiY2xpZW50Il0sImlzcyI6Imh0dHA6XC9cL2xvY2FsaG9zdDo4MDgwXC9vcGVuaWQtY29ubmVjdC1zZXJ2ZXItd2ViYXBwXC8iLCJpYXQiOjE0MTI3ODkzNjh9.xkEJ9IMXpH7qybWXomfq9WOOlpGYnrvGPgey9UQ4GLzbQx7JC0XgJK83PmrmBZosvFPCmota7FzI_BtwoZLgAZfFiH6w3WIlxuogoH-TxmYbxEpTHoTsszZppkq9mNgOlArV4jrR9y3TPo4MovsH71dDhS_ck-CvAlJunHlqhs0\"}," + - "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+0000\"," + "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+00:00\"," + "\"refreshTokenId\":1,\"idTokenId\":1,\"scope\":[\"openid\",\"offline_access\",\"email\",\"profile\"],\"type\":\"Bearer\"," + "\"authenticationHolderId\":2,\"value\":\"eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE0MTI3OTI5NjgsImF1ZCI6WyJjbGllbnQiXSwiaXNzIjoiaHR0cDpcL1wvbG9jYWxob3N0OjgwODBcL29wZW5pZC1jb25uZWN0LXNlcnZlci13ZWJhcHBcLyIsImp0aSI6IjBmZGE5ZmRiLTYyYzItNGIzZS05OTdiLWU0M2VhMDUwMzNiOSIsImlhdCI6MTQxMjc4OTM2OH0.xgaVpRLYE5MzbgXfE0tZt823tjAm6Oh3_kdR1P2I9jRLR6gnTlBQFlYi3Y_0pWNnZSerbAE8Tn6SJHZ9k-curVG0-ByKichV7CNvgsE5X_2wpEaUzejvKf8eZ-BammRY-ie6yxSkAarcUGMvGGOLbkFcz5CtrBpZhfd75J49BIQ\"}" + @@ -1131,8 +1131,8 @@ public WhitelistedSite answer(InvocationOnMock invocation) throws Throwable { @Test public void testExportGrants() throws IOException, ParseException { - Date creationDate1 = formatter.parse("2014-09-10T22:49:44.090+0000", Locale.ENGLISH); - Date accessDate1 = formatter.parse("2014-09-10T23:49:44.090+0000", Locale.ENGLISH); + Date creationDate1 = formatter.parse("2014-09-10T22:49:44.090+00:00", Locale.ENGLISH); + Date accessDate1 = formatter.parse("2014-09-10T23:49:44.090+00:00", Locale.ENGLISH); OAuth2AccessTokenEntity mockToken1 = mock(OAuth2AccessTokenEntity.class); when(mockToken1.getId()).thenReturn(1L); @@ -1146,9 +1146,9 @@ public void testExportGrants() throws IOException, ParseException { site1.setAllowedScopes(ImmutableSet.of("openid", "phone")); when(mockToken1.getApprovedSite()).thenReturn(site1); - Date creationDate2 = formatter.parse("2014-09-11T18:49:44.090+0000", Locale.ENGLISH); - Date accessDate2 = formatter.parse("2014-09-11T20:49:44.090+0000", Locale.ENGLISH); - Date timeoutDate2 = formatter.parse("2014-10-01T20:49:44.090+0000", Locale.ENGLISH); + Date creationDate2 = formatter.parse("2014-09-11T18:49:44.090+00:00", Locale.ENGLISH); + Date accessDate2 = formatter.parse("2014-09-11T20:49:44.090+00:00", Locale.ENGLISH); + Date timeoutDate2 = formatter.parse("2014-10-01T20:49:44.090+00:00", Locale.ENGLISH); ApprovedSite site2 = new ApprovedSite(); site2.setId(2L); @@ -1246,8 +1246,8 @@ public void testExportGrants() throws IOException, ParseException { @Test public void testImportGrants() throws IOException, ParseException { - Date creationDate1 = formatter.parse("2014-09-10T22:49:44.090+0000", Locale.ENGLISH); - Date accessDate1 = formatter.parse("2014-09-10T23:49:44.090+0000", Locale.ENGLISH); + Date creationDate1 = formatter.parse("2014-09-10T22:49:44.090+00:00", Locale.ENGLISH); + Date accessDate1 = formatter.parse("2014-09-10T23:49:44.090+00:00", Locale.ENGLISH); OAuth2AccessTokenEntity mockToken1 = mock(OAuth2AccessTokenEntity.class); when(mockToken1.getId()).thenReturn(1L); @@ -1261,9 +1261,9 @@ public void testImportGrants() throws IOException, ParseException { site1.setAllowedScopes(ImmutableSet.of("openid", "phone")); when(mockToken1.getApprovedSite()).thenReturn(site1); - Date creationDate2 = formatter.parse("2014-09-11T18:49:44.090+0000", Locale.ENGLISH); - Date accessDate2 = formatter.parse("2014-09-11T20:49:44.090+0000", Locale.ENGLISH); - Date timeoutDate2 = formatter.parse("2014-10-01T20:49:44.090+0000", Locale.ENGLISH); + Date creationDate2 = formatter.parse("2014-09-11T18:49:44.090+00:00", Locale.ENGLISH); + Date accessDate2 = formatter.parse("2014-09-11T20:49:44.090+00:00", Locale.ENGLISH); + Date timeoutDate2 = formatter.parse("2014-10-01T20:49:44.090+00:00", Locale.ENGLISH); ApprovedSite site2 = new ApprovedSite(); site2.setId(2L); @@ -1284,11 +1284,11 @@ public void testImportGrants() throws IOException, ParseException { "\"" + MITREidDataService.AUTHENTICATIONHOLDERS + "\": [], " + "\"" + MITREidDataService.GRANTS + "\": [" + - "{\"id\":1,\"clientId\":\"foo\",\"creationDate\":\"2014-09-10T22:49:44.090+0000\",\"accessDate\":\"2014-09-10T23:49:44.090+0000\"," + "{\"id\":1,\"clientId\":\"foo\",\"creationDate\":\"2014-09-10T22:49:44.090+00:00\",\"accessDate\":\"2014-09-10T23:49:44.090+00:00\"," + "\"userId\":\"user1\",\"whitelistedSiteId\":null,\"allowedScopes\":[\"openid\",\"phone\"], \"whitelistedSiteId\":1," + "\"approvedAccessTokens\":[1]}," + - "{\"id\":2,\"clientId\":\"bar\",\"creationDate\":\"2014-09-11T18:49:44.090+0000\",\"accessDate\":\"2014-09-11T20:49:44.090+0000\"," - + "\"timeoutDate\":\"2014-10-01T20:49:44.090+0000\",\"userId\":\"user2\"," + "{\"id\":2,\"clientId\":\"bar\",\"creationDate\":\"2014-09-11T18:49:44.090+00:00\",\"accessDate\":\"2014-09-11T20:49:44.090+00:00\"," + + "\"timeoutDate\":\"2014-10-01T20:49:44.090+00:00\",\"userId\":\"user2\"," + "\"allowedScopes\":[\"openid\",\"offline_access\",\"email\",\"profile\"]}" + " ]" + @@ -1717,7 +1717,7 @@ public void testImportSystemScopes() throws IOException { @Test public void testFixRefreshTokenAuthHolderReferencesOnImport() throws IOException, ParseException { - String expiration1 = "2014-09-10T22:49:44.090+0000"; + String expiration1 = "2014-09-10T22:49:44.090+00:00"; Date expirationDate1 = formatter.parse(expiration1, Locale.ENGLISH); ClientDetailsEntity mockedClient1 = mock(ClientDetailsEntity.class); @@ -1740,7 +1740,7 @@ public void testFixRefreshTokenAuthHolderReferencesOnImport() throws IOException token1.setJwt(JWTParser.parse("eyJhbGciOiJub25lIn0.eyJqdGkiOiJmOTg4OWQyOS0xMTk1LTQ4ODEtODgwZC1lZjVlYzAwY2Y4NDIifQ.")); token1.setAuthenticationHolder(holder1); - String expiration2 = "2015-01-07T18:31:50.079+0000"; + String expiration2 = "2015-01-07T18:31:50.079+00:00"; Date expirationDate2 = formatter.parse(expiration2, Locale.ENGLISH); ClientDetailsEntity mockedClient2 = mock(ClientDetailsEntity.class); @@ -1779,9 +1779,9 @@ public void testFixRefreshTokenAuthHolderReferencesOnImport() throws IOException " ]," + "\"" + MITREidDataService.REFRESHTOKENS + "\": [" + - "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+0000\"," + "{\"id\":1,\"clientId\":\"mocked_client_1\",\"expiration\":\"2014-09-10T22:49:44.090+00:00\"," + "\"authenticationHolderId\":1,\"value\":\"eyJhbGciOiJub25lIn0.eyJqdGkiOiJmOTg4OWQyOS0xMTk1LTQ4ODEtODgwZC1lZjVlYzAwY2Y4NDIifQ.\"}," + - "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+0000\"," + "{\"id\":2,\"clientId\":\"mocked_client_2\",\"expiration\":\"2015-01-07T18:31:50.079+00:00\"," + "\"authenticationHolderId\":2,\"value\":\"eyJhbGciOiJub25lIn0.eyJqdGkiOiJlYmEyYjc3My0xNjAzLTRmNDAtOWQ3MS1hMGIxZDg1OWE2MDAifQ.\"}" + " ]" + diff --git a/pom.xml b/pom.xml index 6824f13603..a3b42f22a3 100644 --- a/pom.xml +++ b/pom.xml @@ -70,7 +70,7 @@ - 1.8 + 11 1.7.25 A reference implementation of OpenID Connect (http://openid.net/connect/), OAuth 2.0, and UMA built on top of Java, Spring, and Spring Security. The project contains a fully functioning server, client, and utility library. @@ -96,7 +96,7 @@ org.jacoco jacoco-maven-plugin - 0.7.9 + 0.8.7 org.apache.maven.plugins @@ -178,7 +178,7 @@ ro.isdc.wro4j wro4j-maven-plugin - 1.8.0 + 1.10.0 compile @@ -191,7 +191,7 @@ ro.isdc.wro4j wro4j-extensions - 1.8.0 + 1.10.0 @@ -365,7 +365,7 @@ org.springframework spring-framework-bom - 4.3.22.RELEASE + 5.3.9 pom import @@ -386,7 +386,7 @@ org.springframework.security spring-security-bom - 4.2.11.RELEASE + 5.5.2 pom import @@ -605,7 +605,34 @@ ro.isdc.wro4j wro4j-extensions - 1.8.0 + 1.10.0 + + + + + javax.annotation + javax.annotation-api + 1.3.2 + + + jakarta.xml.bind + jakarta.xml.bind-api + 3.0.0 + + + javax.xml.bind + jaxb-api + 2.3.1 + + + javax.activation + activation + 1.1 + + + org.glassfish.jaxb + jaxb-runtime + 2.3.0-b170127.1453 From a0bd2c70ac75c92f73f6de122e08a4bd155e7774 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 20 Dec 2021 13:09:08 -0500 Subject: [PATCH 460/465] [maven-release-plugin] prepare release mitreid-connect-1.3.4 --- openid-connect-client/pom.xml | 2 +- openid-connect-common/pom.xml | 2 +- openid-connect-server-webapp/pom.xml | 2 +- openid-connect-server/pom.xml | 2 +- pom.xml | 2 +- uma-server-webapp/pom.xml | 2 +- uma-server/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/openid-connect-client/pom.xml b/openid-connect-client/pom.xml index b891d4e0e6..e2f9399cb5 100644 --- a/openid-connect-client/pom.xml +++ b/openid-connect-client/pom.xml @@ -22,7 +22,7 @@ openid-connect-parent org.mitre - 1.3.4-SNAPSHOT + 1.3.4 .. openid-connect-client diff --git a/openid-connect-common/pom.xml b/openid-connect-common/pom.xml index a2b88b5179..cab527332f 100644 --- a/openid-connect-common/pom.xml +++ b/openid-connect-common/pom.xml @@ -22,7 +22,7 @@ openid-connect-parent org.mitre - 1.3.4-SNAPSHOT + 1.3.4 .. openid-connect-common diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index 11881547f7..bf2a37479c 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -21,7 +21,7 @@ org.mitre openid-connect-parent - 1.3.4-SNAPSHOT + 1.3.4 openid-connect-server-webapp war diff --git a/openid-connect-server/pom.xml b/openid-connect-server/pom.xml index 84fe62198e..98aebae3ad 100644 --- a/openid-connect-server/pom.xml +++ b/openid-connect-server/pom.xml @@ -23,7 +23,7 @@ org.mitre openid-connect-parent - 1.3.4-SNAPSHOT + 1.3.4 .. diff --git a/pom.xml b/pom.xml index 6824f13603..0dcf6805ae 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.mitre openid-connect-parent - 1.3.4-SNAPSHOT + 1.3.4 MITREid Connect pom diff --git a/uma-server-webapp/pom.xml b/uma-server-webapp/pom.xml index e0485e03a5..5e8de8840c 100644 --- a/uma-server-webapp/pom.xml +++ b/uma-server-webapp/pom.xml @@ -19,7 +19,7 @@ org.mitre openid-connect-parent - 1.3.4-SNAPSHOT + 1.3.4 .. uma-server-webapp diff --git a/uma-server/pom.xml b/uma-server/pom.xml index 2373d34c1c..d063dcc4a3 100644 --- a/uma-server/pom.xml +++ b/uma-server/pom.xml @@ -19,7 +19,7 @@ org.mitre openid-connect-parent - 1.3.4-SNAPSHOT + 1.3.4 .. uma-server From f5df7621533a79a9a738a6301444a50753bcfb22 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Mon, 20 Dec 2021 13:09:11 -0500 Subject: [PATCH 461/465] [maven-release-plugin] prepare for next development iteration --- openid-connect-client/pom.xml | 2 +- openid-connect-common/pom.xml | 2 +- openid-connect-server-webapp/pom.xml | 2 +- openid-connect-server/pom.xml | 2 +- pom.xml | 2 +- uma-server-webapp/pom.xml | 2 +- uma-server/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/openid-connect-client/pom.xml b/openid-connect-client/pom.xml index e2f9399cb5..3fbbd9e5ec 100644 --- a/openid-connect-client/pom.xml +++ b/openid-connect-client/pom.xml @@ -22,7 +22,7 @@ openid-connect-parent org.mitre - 1.3.4 + 1.3.5-SNAPSHOT .. openid-connect-client diff --git a/openid-connect-common/pom.xml b/openid-connect-common/pom.xml index cab527332f..08a1111498 100644 --- a/openid-connect-common/pom.xml +++ b/openid-connect-common/pom.xml @@ -22,7 +22,7 @@ openid-connect-parent org.mitre - 1.3.4 + 1.3.5-SNAPSHOT .. openid-connect-common diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index bf2a37479c..a294b1d8bb 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -21,7 +21,7 @@ org.mitre openid-connect-parent - 1.3.4 + 1.3.5-SNAPSHOT openid-connect-server-webapp war diff --git a/openid-connect-server/pom.xml b/openid-connect-server/pom.xml index 98aebae3ad..eff1246112 100644 --- a/openid-connect-server/pom.xml +++ b/openid-connect-server/pom.xml @@ -23,7 +23,7 @@ org.mitre openid-connect-parent - 1.3.4 + 1.3.5-SNAPSHOT .. diff --git a/pom.xml b/pom.xml index 0dcf6805ae..d85b71930e 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.mitre openid-connect-parent - 1.3.4 + 1.3.5-SNAPSHOT MITREid Connect pom diff --git a/uma-server-webapp/pom.xml b/uma-server-webapp/pom.xml index 5e8de8840c..a1db8a2739 100644 --- a/uma-server-webapp/pom.xml +++ b/uma-server-webapp/pom.xml @@ -19,7 +19,7 @@ org.mitre openid-connect-parent - 1.3.4 + 1.3.5-SNAPSHOT .. uma-server-webapp diff --git a/uma-server/pom.xml b/uma-server/pom.xml index d063dcc4a3..a35038b57e 100644 --- a/uma-server/pom.xml +++ b/uma-server/pom.xml @@ -19,7 +19,7 @@ org.mitre openid-connect-parent - 1.3.4 + 1.3.5-SNAPSHOT .. uma-server From 8a58d1260020eeb5121eb4f2097209441919ebfa Mon Sep 17 00:00:00 2001 From: faidh Date: Fri, 25 Mar 2022 11:11:55 +0200 Subject: [PATCH 462/465] Merge latest MitreID with updated 3pps back to GitHub fork --- openid-connect-client/pom.xml | 2 +- openid-connect-common/pom.xml | 2 +- openid-connect-server-webapp/pom.xml | 2 +- .../src/main/webapp/WEB-INF/tags/header.tag | 1 + .../main/webapp/resources/js/lib/backbone.js | 3955 +-- .../main/webapp/resources/js/lib/jquery.js | 17218 +++++------ .../resources/js/lib/moment-with-locales.js | 24858 +++++++++++----- .../webapp/resources/js/lib/underscore.js | 3128 +- openid-connect-server/pom.xml | 2 +- pom.xml | 2 +- uma-server-webapp/pom.xml | 2 +- uma-server/pom.xml | 4 +- 12 files changed, 29385 insertions(+), 19791 deletions(-) diff --git a/openid-connect-client/pom.xml b/openid-connect-client/pom.xml index 3fbbd9e5ec..0767d3f271 100644 --- a/openid-connect-client/pom.xml +++ b/openid-connect-client/pom.xml @@ -22,7 +22,7 @@ openid-connect-parent org.mitre - 1.3.5-SNAPSHOT + 1.3.5 .. openid-connect-client diff --git a/openid-connect-common/pom.xml b/openid-connect-common/pom.xml index 08a1111498..e091d67364 100644 --- a/openid-connect-common/pom.xml +++ b/openid-connect-common/pom.xml @@ -22,7 +22,7 @@ openid-connect-parent org.mitre - 1.3.5-SNAPSHOT + 1.3.5 .. openid-connect-common diff --git a/openid-connect-server-webapp/pom.xml b/openid-connect-server-webapp/pom.xml index a294b1d8bb..a529cbd18b 100644 --- a/openid-connect-server-webapp/pom.xml +++ b/openid-connect-server-webapp/pom.xml @@ -21,7 +21,7 @@ org.mitre openid-connect-parent - 1.3.5-SNAPSHOT + 1.3.5 openid-connect-server-webapp war diff --git a/openid-connect-server-webapp/src/main/webapp/WEB-INF/tags/header.tag b/openid-connect-server-webapp/src/main/webapp/WEB-INF/tags/header.tag index f4b4430cf9..94f68be330 100644 --- a/openid-connect-server-webapp/src/main/webapp/WEB-INF/tags/header.tag +++ b/openid-connect-server-webapp/src/main/webapp/WEB-INF/tags/header.tag @@ -14,6 +14,7 @@ + diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/lib/backbone.js b/openid-connect-server-webapp/src/main/webapp/resources/js/lib/backbone.js index 58800425c7..3cdcfdc821 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/lib/backbone.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/lib/backbone.js @@ -1,1873 +1,2096 @@ -// Backbone.js 1.2.1 +// Backbone.js 1.4.0 -// (c) 2010-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +// (c) 2010-2019 Jeremy Ashkenas and DocumentCloud // Backbone may be freely distributed under the MIT license. // For all details and documentation: // http://backbonejs.org (function(factory) { - // Establish the root object, `window` (`self`) in the browser, or `global` on the server. - // We use `self` instead of `window` for `WebWorker` support. - var root = (typeof self == 'object' && self.self == self && self) || - (typeof global == 'object' && global.global == global && global); - - // Set up Backbone appropriately for the environment. Start with AMD. - if (typeof define === 'function' && define.amd) { - define(['underscore', 'jquery', 'exports'], function(_, $, exports) { - // Export global even in AMD case in case this script is loaded with - // others that may still expect a global Backbone. - root.Backbone = factory(root, exports, _, $); - }); - - // Next for Node.js or CommonJS. jQuery may not be needed as a module. - } else if (typeof exports !== 'undefined') { - var _ = require('underscore'), $; - try { $ = require('jquery'); } catch(e) {} - factory(root, exports, _, $); - - // Finally, as a browser global. - } else { - root.Backbone = factory(root, {}, root._, (root.jQuery || root.Zepto || root.ender || root.$)); - } - -}(function(root, Backbone, _, $) { - - // Initial Setup - // ------------- - - // Save the previous value of the `Backbone` variable, so that it can be - // restored later on, if `noConflict` is used. - var previousBackbone = root.Backbone; - - // Create a local reference to a common array method we'll want to use later. - var slice = [].slice; - - // Current version of the library. Keep in sync with `package.json`. - Backbone.VERSION = '1.2.1'; - - // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns - // the `$` variable. - Backbone.$ = $; - - // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable - // to its previous owner. Returns a reference to this Backbone object. - Backbone.noConflict = function() { - root.Backbone = previousBackbone; - return this; - }; - - // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option - // will fake `"PATCH"`, `"PUT"` and `"DELETE"` requests via the `_method` parameter and - // set a `X-Http-Method-Override` header. - Backbone.emulateHTTP = false; - - // Turn on `emulateJSON` to support legacy servers that can't deal with direct - // `application/json` requests ... this will encode the body as - // `application/x-www-form-urlencoded` instead and will send the model in a - // form param named `model`. - Backbone.emulateJSON = false; - - // Proxy Underscore methods to a Backbone class' prototype using a - // particular attribute as the data argument - var addMethod = function(length, method, attribute) { - switch (length) { - case 1: return function() { - return _[method](this[attribute]); - }; - case 2: return function(value) { - return _[method](this[attribute], value); - }; - case 3: return function(iteratee, context) { - return _[method](this[attribute], iteratee, context); - }; - case 4: return function(iteratee, defaultVal, context) { - return _[method](this[attribute], iteratee, defaultVal, context); - }; - default: return function() { - var args = slice.call(arguments); - args.unshift(this[attribute]); - return _[method].apply(_, args); - }; - } - }; - var addUnderscoreMethods = function(Class, methods, attribute) { - _.each(methods, function(length, method) { - if (_[method]) Class.prototype[method] = addMethod(length, method, attribute); - }); - }; - - // Backbone.Events - // --------------- - - // A module that can be mixed in to *any object* in order to provide it with - // custom events. You may bind with `on` or remove with `off` callback - // functions to an event; `trigger`-ing an event fires all callbacks in - // succession. - // - // var object = {}; - // _.extend(object, Backbone.Events); - // object.on('expand', function(){ alert('expanded'); }); - // object.trigger('expand'); - // - var Events = Backbone.Events = {}; - - // Regular expression used to split event strings. - var eventSplitter = /\s+/; - - // Iterates over the standard `event, callback` (as well as the fancy multiple - // space-separated events `"change blur", callback` and jQuery-style event - // maps `{event: callback}`), reducing them by manipulating `memo`. - // Passes a normalized single event name and callback, as well as any - // optional `opts`. - var eventsApi = function(iteratee, memo, name, callback, opts) { - var i = 0, names; - if (name && typeof name === 'object') { - // Handle event maps. - if (callback !== void 0 && 'context' in opts && opts.context === void 0) opts.context = callback; - for (names = _.keys(name); i < names.length ; i++) { - memo = iteratee(memo, names[i], name[names[i]], opts); - } - } else if (name && eventSplitter.test(name)) { - // Handle space separated event names. - for (names = name.split(eventSplitter); i < names.length; i++) { - memo = iteratee(memo, names[i], callback, opts); - } - } else { - memo = iteratee(memo, name, callback, opts); - } - return memo; - }; - - // Bind an event to a `callback` function. Passing `"all"` will bind - // the callback to all events fired. - Events.on = function(name, callback, context) { - return internalOn(this, name, callback, context); - }; - - // An internal use `on` function, used to guard the `listening` argument from - // the public API. - var internalOn = function(obj, name, callback, context, listening) { - obj._events = eventsApi(onApi, obj._events || {}, name, callback, { - context: context, - ctx: obj, - listening: listening - }); - - if (listening) { - var listeners = obj._listeners || (obj._listeners = {}); - listeners[listening.id] = listening; - } - - return obj; - }; - - // Inversion-of-control versions of `on`. Tell *this* object to listen to - // an event in another object... keeping track of what it's listening to. - Events.listenTo = function(obj, name, callback) { - if (!obj) return this; - var id = obj._listenId || (obj._listenId = _.uniqueId('l')); - var listeningTo = this._listeningTo || (this._listeningTo = {}); - var listening = listeningTo[id]; - - // This object is not listening to any other events on `obj` yet. - // Setup the necessary references to track the listening callbacks. - if (!listening) { - var thisId = this._listenId || (this._listenId = _.uniqueId('l')); - listening = listeningTo[id] = {obj: obj, objId: id, id: thisId, listeningTo: listeningTo, count: 0}; - } - - // Bind callbacks on obj, and keep track of them on listening. - internalOn(obj, name, callback, this, listening); - return this; - }; - - // The reducing API that adds a callback to the `events` object. - var onApi = function(events, name, callback, options) { - if (callback) { - var handlers = events[name] || (events[name] = []); - var context = options.context, ctx = options.ctx, listening = options.listening; - if (listening) listening.count++; - - handlers.push({ callback: callback, context: context, ctx: context || ctx, listening: listening }); - } - return events; - }; - - // Remove one or many callbacks. If `context` is null, removes all - // callbacks with that function. If `callback` is null, removes all - // callbacks for the event. If `name` is null, removes all bound - // callbacks for all events. - Events.off = function(name, callback, context) { - if (!this._events) return this; - this._events = eventsApi(offApi, this._events, name, callback, { - context: context, - listeners: this._listeners - }); - return this; - }; - - // Tell this object to stop listening to either specific events ... or - // to every object it's currently listening to. - Events.stopListening = function(obj, name, callback) { - var listeningTo = this._listeningTo; - if (!listeningTo) return this; - - var ids = obj ? [obj._listenId] : _.keys(listeningTo); - - for (var i = 0; i < ids.length; i++) { - var listening = listeningTo[ids[i]]; - - // If listening doesn't exist, this object is not currently - // listening to obj. Break out early. - if (!listening) break; - - listening.obj.off(name, callback, this); - } - if (_.isEmpty(listeningTo)) this._listeningTo = void 0; - - return this; - }; - - // The reducing API that removes a callback from the `events` object. - var offApi = function(events, name, callback, options) { - // No events to consider. - if (!events) return; - - var i = 0, listening; - var context = options.context, listeners = options.listeners; - - // Delete all events listeners and "drop" events. - if (!name && !callback && !context) { - var ids = _.keys(listeners); - for (; i < ids.length; i++) { - listening = listeners[ids[i]]; - delete listeners[listening.id]; - delete listening.listeningTo[listening.objId]; - } - return; - } - - var names = name ? [name] : _.keys(events); - for (; i < names.length; i++) { - name = names[i]; - var handlers = events[name]; - - // Bail out if there are no events stored. - if (!handlers) break; - - // Replace events if there are any remaining. Otherwise, clean up. - var remaining = []; - for (var j = 0; j < handlers.length; j++) { - var handler = handlers[j]; - if ( - callback && callback !== handler.callback && - callback !== handler.callback._callback || - context && context !== handler.context - ) { - remaining.push(handler); - } else { - listening = handler.listening; - if (listening && --listening.count === 0) { - delete listeners[listening.id]; - delete listening.listeningTo[listening.objId]; - } - } - } - - // Update tail event if the list has any events. Otherwise, clean up. - if (remaining.length) { - events[name] = remaining; - } else { - delete events[name]; - } - } - if (_.size(events)) return events; - }; - - // Bind an event to only be triggered a single time. After the first time - // the callback is invoked, it will be removed. When multiple events are - // passed in using the space-separated syntax, the event will fire once for every - // event you passed in, not once for a combination of all events - Events.once = function(name, callback, context) { - // Map the event into a `{event: once}` object. - var events = eventsApi(onceMap, {}, name, callback, _.bind(this.off, this)); - return this.on(events, void 0, context); - }; - - // Inversion-of-control versions of `once`. - Events.listenToOnce = function(obj, name, callback) { - // Map the event into a `{event: once}` object. - var events = eventsApi(onceMap, {}, name, callback, _.bind(this.stopListening, this, obj)); - return this.listenTo(obj, events); - }; - - // Reduces the event callbacks into a map of `{event: onceWrapper}`. - // `offer` unbinds the `onceWrapper` after it has been called. - var onceMap = function(map, name, callback, offer) { - if (callback) { - var once = map[name] = _.once(function() { - offer(name, once); - callback.apply(this, arguments); - }); - once._callback = callback; - } - return map; - }; - - // Trigger one or many events, firing all bound callbacks. Callbacks are - // passed the same arguments as `trigger` is, apart from the event name - // (unless you're listening on `"all"`, which will cause your callback to - // receive the true name of the event as the first argument). - Events.trigger = function(name) { - if (!this._events) return this; - - var length = Math.max(0, arguments.length - 1); - var args = Array(length); - for (var i = 0; i < length; i++) args[i] = arguments[i + 1]; - - eventsApi(triggerApi, this._events, name, void 0, args); - return this; - }; - - // Handles triggering the appropriate event callbacks. - var triggerApi = function(objEvents, name, cb, args) { - if (objEvents) { - var events = objEvents[name]; - var allEvents = objEvents.all; - if (events && allEvents) allEvents = allEvents.slice(); - if (events) triggerEvents(events, args); - if (allEvents) triggerEvents(allEvents, [name].concat(args)); - } - return objEvents; - }; - - // A difficult-to-believe, but optimized internal dispatch function for - // triggering events. Tries to keep the usual cases speedy (most internal - // Backbone events have 3 arguments). - var triggerEvents = function(events, args) { - var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2]; - switch (args.length) { - case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return; - case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return; - case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return; - case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return; - default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); return; - } - }; - - // Aliases for backwards compatibility. - Events.bind = Events.on; - Events.unbind = Events.off; - - // Allow the `Backbone` object to serve as a global event bus, for folks who - // want global "pubsub" in a convenient place. - _.extend(Backbone, Events); - - // Backbone.Model - // -------------- - - // Backbone **Models** are the basic data object in the framework -- - // frequently representing a row in a table in a database on your server. - // A discrete chunk of data and a bunch of useful, related methods for - // performing computations and transformations on that data. - - // Create a new model with the specified attributes. A client id (`cid`) - // is automatically generated and assigned for you. - var Model = Backbone.Model = function(attributes, options) { - var attrs = attributes || {}; - options || (options = {}); - this.cid = _.uniqueId(this.cidPrefix); - this.attributes = {}; - if (options.collection) this.collection = options.collection; - if (options.parse) attrs = this.parse(attrs, options) || {}; - attrs = _.defaults({}, attrs, _.result(this, 'defaults')); - this.set(attrs, options); - this.changed = {}; - this.initialize.apply(this, arguments); - }; - - // Attach all inheritable methods to the Model prototype. - _.extend(Model.prototype, Events, { - - // A hash of attributes whose current and previous value differ. - changed: null, - - // The value returned during the last failed validation. - validationError: null, - - // The default name for the JSON `id` attribute is `"id"`. MongoDB and - // CouchDB users may want to set this to `"_id"`. - idAttribute: 'id', - - // The prefix is used to create the client id which is used to identify models locally. - // You may want to override this if you're experiencing name clashes with model ids. - cidPrefix: 'c', - - // Initialize is an empty function by default. Override it with your own - // initialization logic. - initialize: function(){}, - - // Return a copy of the model's `attributes` object. - toJSON: function(options) { - return _.clone(this.attributes); - }, - - // Proxy `Backbone.sync` by default -- but override this if you need - // custom syncing semantics for *this* particular model. - sync: function() { - return Backbone.sync.apply(this, arguments); - }, - - // Get the value of an attribute. - get: function(attr) { - return this.attributes[attr]; - }, - - // Get the HTML-escaped value of an attribute. - escape: function(attr) { - return _.escape(this.get(attr)); - }, - - // Returns `true` if the attribute contains a value that is not null - // or undefined. - has: function(attr) { - return this.get(attr) != null; - }, - - // Special-cased proxy to underscore's `_.matches` method. - matches: function(attrs) { - return !!_.iteratee(attrs, this)(this.attributes); - }, - - // Set a hash of model attributes on the object, firing `"change"`. This is - // the core primitive operation of a model, updating the data and notifying - // anyone who needs to know about the change in state. The heart of the beast. - set: function(key, val, options) { - if (key == null) return this; - - // Handle both `"key", value` and `{key: value}` -style arguments. - var attrs; - if (typeof key === 'object') { - attrs = key; - options = val; - } else { - (attrs = {})[key] = val; - } - - options || (options = {}); - - // Run validation. - if (!this._validate(attrs, options)) return false; - - // Extract attributes and options. - var unset = options.unset; - var silent = options.silent; - var changes = []; - var changing = this._changing; - this._changing = true; - - if (!changing) { - this._previousAttributes = _.clone(this.attributes); - this.changed = {}; - } - - var current = this.attributes; - var changed = this.changed; - var prev = this._previousAttributes; - - // Check for changes of `id`. - if (this.idAttribute in attrs) this.id = attrs[this.idAttribute]; - - // For each `set` attribute, update or delete the current value. - for (var attr in attrs) { - val = attrs[attr]; - if (!_.isEqual(current[attr], val)) changes.push(attr); - if (!_.isEqual(prev[attr], val)) { - changed[attr] = val; - } else { - delete changed[attr]; - } - unset ? delete current[attr] : current[attr] = val; - } - - // Trigger all relevant attribute changes. - if (!silent) { - if (changes.length) this._pending = options; - for (var i = 0; i < changes.length; i++) { - this.trigger('change:' + changes[i], this, current[changes[i]], options); - } - } - - // You might be wondering why there's a `while` loop here. Changes can - // be recursively nested within `"change"` events. - if (changing) return this; - if (!silent) { - while (this._pending) { - options = this._pending; - this._pending = false; - this.trigger('change', this, options); - } - } - this._pending = false; - this._changing = false; - return this; - }, - - // Remove an attribute from the model, firing `"change"`. `unset` is a noop - // if the attribute doesn't exist. - unset: function(attr, options) { - return this.set(attr, void 0, _.extend({}, options, {unset: true})); - }, - - // Clear all attributes on the model, firing `"change"`. - clear: function(options) { - var attrs = {}; - for (var key in this.attributes) attrs[key] = void 0; - return this.set(attrs, _.extend({}, options, {unset: true})); - }, - - // Determine if the model has changed since the last `"change"` event. - // If you specify an attribute name, determine if that attribute has changed. - hasChanged: function(attr) { - if (attr == null) return !_.isEmpty(this.changed); - return _.has(this.changed, attr); - }, - - // Return an object containing all the attributes that have changed, or - // false if there are no changed attributes. Useful for determining what - // parts of a view need to be updated and/or what attributes need to be - // persisted to the server. Unset attributes will be set to undefined. - // You can also pass an attributes object to diff against the model, - // determining if there *would be* a change. - changedAttributes: function(diff) { - if (!diff) return this.hasChanged() ? _.clone(this.changed) : false; - var old = this._changing ? this._previousAttributes : this.attributes; - var changed = {}; - for (var attr in diff) { - var val = diff[attr]; - if (_.isEqual(old[attr], val)) continue; - changed[attr] = val; - } - return _.size(changed) ? changed : false; - }, - - // Get the previous value of an attribute, recorded at the time the last - // `"change"` event was fired. - previous: function(attr) { - if (attr == null || !this._previousAttributes) return null; - return this._previousAttributes[attr]; - }, - - // Get all of the attributes of the model at the time of the previous - // `"change"` event. - previousAttributes: function() { - return _.clone(this._previousAttributes); - }, - - // Fetch the model from the server, merging the response with the model's - // local attributes. Any changed attributes will trigger a "change" event. - fetch: function(options) { - options = _.extend({parse: true}, options); - var model = this; - var success = options.success; - options.success = function(resp) { - var serverAttrs = options.parse ? model.parse(resp, options) : resp; - if (!model.set(serverAttrs, options)) return false; - if (success) success.call(options.context, model, resp, options); - model.trigger('sync', model, resp, options); - }; - wrapError(this, options); - return this.sync('read', this, options); - }, - - // Set a hash of model attributes, and sync the model to the server. - // If the server returns an attributes hash that differs, the model's - // state will be `set` again. - save: function(key, val, options) { - // Handle both `"key", value` and `{key: value}` -style arguments. - var attrs; - if (key == null || typeof key === 'object') { - attrs = key; - options = val; - } else { - (attrs = {})[key] = val; - } - - options = _.extend({validate: true, parse: true}, options); - var wait = options.wait; - - // If we're not waiting and attributes exist, save acts as - // `set(attr).save(null, opts)` with validation. Otherwise, check if - // the model will be valid when the attributes, if any, are set. - if (attrs && !wait) { - if (!this.set(attrs, options)) return false; - } else { - if (!this._validate(attrs, options)) return false; - } - - // After a successful server-side save, the client is (optionally) - // updated with the server-side state. - var model = this; - var success = options.success; - var attributes = this.attributes; - options.success = function(resp) { - // Ensure attributes are restored during synchronous saves. - model.attributes = attributes; - var serverAttrs = options.parse ? model.parse(resp, options) : resp; - if (wait) serverAttrs = _.extend({}, attrs, serverAttrs); - if (serverAttrs && !model.set(serverAttrs, options)) return false; - if (success) success.call(options.context, model, resp, options); - model.trigger('sync', model, resp, options); - }; - wrapError(this, options); - - // Set temporary attributes if `{wait: true}` to properly find new ids. - if (attrs && wait) this.attributes = _.extend({}, attributes, attrs); - - var method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update'); - if (method === 'patch' && !options.attrs) options.attrs = attrs; - var xhr = this.sync(method, this, options); - - // Restore attributes. - this.attributes = attributes; - - return xhr; - }, - - // Destroy this model on the server if it was already persisted. - // Optimistically removes the model from its collection, if it has one. - // If `wait: true` is passed, waits for the server to respond before removal. - destroy: function(options) { - options = options ? _.clone(options) : {}; - var model = this; - var success = options.success; - var wait = options.wait; - - var destroy = function() { - model.stopListening(); - model.trigger('destroy', model, model.collection, options); - }; - - options.success = function(resp) { - if (wait) destroy(); - if (success) success.call(options.context, model, resp, options); - if (!model.isNew()) model.trigger('sync', model, resp, options); - }; - - var xhr = false; - if (this.isNew()) { - _.defer(options.success); - } else { - wrapError(this, options); - xhr = this.sync('delete', this, options); - } - if (!wait) destroy(); - return xhr; - }, - - // Default URL for the model's representation on the server -- if you're - // using Backbone's restful methods, override this to change the endpoint - // that will be called. - url: function() { - var base = - _.result(this, 'urlRoot') || - _.result(this.collection, 'url') || - urlError(); - if (this.isNew()) return base; - var id = this.get(this.idAttribute); - return base.replace(/[^\/]$/, '$&/') + encodeURIComponent(id); - }, - - // **parse** converts a response into the hash of attributes to be `set` on - // the model. The default implementation is just to pass the response along. - parse: function(resp, options) { - return resp; - }, - - // Create a new model with identical attributes to this one. - clone: function() { - return new this.constructor(this.attributes); - }, - - // A model is new if it has never been saved to the server, and lacks an id. - isNew: function() { - return !this.has(this.idAttribute); - }, - - // Check if the model is currently in a valid state. - isValid: function(options) { - return this._validate({}, _.defaults({validate: true}, options)); - }, - - // Run validation against the next complete set of model attributes, - // returning `true` if all is well. Otherwise, fire an `"invalid"` event. - _validate: function(attrs, options) { - if (!options.validate || !this.validate) return true; - attrs = _.extend({}, this.attributes, attrs); - var error = this.validationError = this.validate(attrs, options) || null; - if (!error) return true; - this.trigger('invalid', this, error, _.extend(options, {validationError: error})); - return false; - } - - }); - - // Underscore methods that we want to implement on the Model. - var modelMethods = { keys: 1, values: 1, pairs: 1, invert: 1, pick: 0, - omit: 0, chain: 1, isEmpty: 1 }; - - // Mix in each Underscore method as a proxy to `Model#attributes`. - addUnderscoreMethods(Model, modelMethods, 'attributes'); - - // Backbone.Collection - // ------------------- - - // If models tend to represent a single row of data, a Backbone Collection is - // more analogous to a table full of data ... or a small slice or page of that - // table, or a collection of rows that belong together for a particular reason - // -- all of the messages in this particular folder, all of the documents - // belonging to this particular author, and so on. Collections maintain - // indexes of their models, both in order, and for lookup by `id`. - - // Create a new **Collection**, perhaps to contain a specific type of `model`. - // If a `comparator` is specified, the Collection will maintain - // its models in sort order, as they're added and removed. - var Collection = Backbone.Collection = function(models, options) { - options || (options = {}); - if (options.model) this.model = options.model; - if (options.comparator !== void 0) this.comparator = options.comparator; - this._reset(); - this.initialize.apply(this, arguments); - if (models) this.reset(models, _.extend({silent: true}, options)); - }; - - // Default options for `Collection#set`. - var setOptions = {add: true, remove: true, merge: true}; - var addOptions = {add: true, remove: false}; - - // Define the Collection's inheritable methods. - _.extend(Collection.prototype, Events, { - - // The default model for a collection is just a **Backbone.Model**. - // This should be overridden in most cases. - model: Model, - - // Initialize is an empty function by default. Override it with your own - // initialization logic. - initialize: function(){}, - - // The JSON representation of a Collection is an array of the - // models' attributes. - toJSON: function(options) { - return this.map(function(model) { return model.toJSON(options); }); - }, - - // Proxy `Backbone.sync` by default. - sync: function() { - return Backbone.sync.apply(this, arguments); - }, - - // Add a model, or list of models to the set. - add: function(models, options) { - return this.set(models, _.extend({merge: false}, options, addOptions)); - }, - - // Remove a model, or a list of models from the set. - remove: function(models, options) { - options = _.extend({}, options); - var singular = !_.isArray(models); - models = singular ? [models] : _.clone(models); - var removed = this._removeModels(models, options); - if (!options.silent && removed) this.trigger('update', this, options); - return singular ? removed[0] : removed; - }, - - // Update a collection by `set`-ing a new list of models, adding new ones, - // removing models that are no longer present, and merging models that - // already exist in the collection, as necessary. Similar to **Model#set**, - // the core operation for updating the data contained by the collection. - set: function(models, options) { - options = _.defaults({}, options, setOptions); - if (options.parse && !this._isModel(models)) models = this.parse(models, options); - var singular = !_.isArray(models); - models = singular ? (models ? [models] : []) : models.slice(); - var id, model, attrs, existing, sort; - var at = options.at; - if (at != null) at = +at; - if (at < 0) at += this.length + 1; - var sortable = this.comparator && (at == null) && options.sort !== false; - var sortAttr = _.isString(this.comparator) ? this.comparator : null; - var toAdd = [], toRemove = [], modelMap = {}; - var add = options.add, merge = options.merge, remove = options.remove; - var order = !sortable && add && remove ? [] : false; - var orderChanged = false; - - // Turn bare objects into model references, and prevent invalid models - // from being added. - for (var i = 0; i < models.length; i++) { - attrs = models[i]; - - // If a duplicate is found, prevent it from being added and - // optionally merge it into the existing model. - if (existing = this.get(attrs)) { - if (remove) modelMap[existing.cid] = true; - if (merge && attrs !== existing) { - attrs = this._isModel(attrs) ? attrs.attributes : attrs; - if (options.parse) attrs = existing.parse(attrs, options); - existing.set(attrs, options); - if (sortable && !sort && existing.hasChanged(sortAttr)) sort = true; - } - models[i] = existing; - - // If this is a new, valid model, push it to the `toAdd` list. - } else if (add) { - model = models[i] = this._prepareModel(attrs, options); - if (!model) continue; - toAdd.push(model); - this._addReference(model, options); - } - - // Do not add multiple models with the same `id`. - model = existing || model; - if (!model) continue; - id = this.modelId(model.attributes); - if (order && (model.isNew() || !modelMap[id])) { - order.push(model); - - // Check to see if this is actually a new model at this index. - orderChanged = orderChanged || !this.models[i] || model.cid !== this.models[i].cid; - } - - modelMap[id] = true; - } - - // Remove nonexistent models if appropriate. - if (remove) { - for (var i = 0; i < this.length; i++) { - if (!modelMap[(model = this.models[i]).cid]) toRemove.push(model); - } - if (toRemove.length) this._removeModels(toRemove, options); - } - - // See if sorting is needed, update `length` and splice in new models. - if (toAdd.length || orderChanged) { - if (sortable) sort = true; - this.length += toAdd.length; - if (at != null) { - for (var i = 0; i < toAdd.length; i++) { - this.models.splice(at + i, 0, toAdd[i]); - } - } else { - if (order) this.models.length = 0; - var orderedModels = order || toAdd; - for (var i = 0; i < orderedModels.length; i++) { - this.models.push(orderedModels[i]); - } - } - } - - // Silently sort the collection if appropriate. - if (sort) this.sort({silent: true}); - - // Unless silenced, it's time to fire all appropriate add/sort events. - if (!options.silent) { - var addOpts = at != null ? _.clone(options) : options; - for (var i = 0; i < toAdd.length; i++) { - if (at != null) addOpts.index = at + i; - (model = toAdd[i]).trigger('add', model, this, addOpts); - } - if (sort || orderChanged) this.trigger('sort', this, options); - if (toAdd.length || toRemove.length) this.trigger('update', this, options); - } - - // Return the added (or merged) model (or models). - return singular ? models[0] : models; - }, - - // When you have more items than you want to add or remove individually, - // you can reset the entire set with a new list of models, without firing - // any granular `add` or `remove` events. Fires `reset` when finished. - // Useful for bulk operations and optimizations. - reset: function(models, options) { - options = options ? _.clone(options) : {}; - for (var i = 0; i < this.models.length; i++) { - this._removeReference(this.models[i], options); - } - options.previousModels = this.models; - this._reset(); - models = this.add(models, _.extend({silent: true}, options)); - if (!options.silent) this.trigger('reset', this, options); - return models; - }, - - // Add a model to the end of the collection. - push: function(model, options) { - return this.add(model, _.extend({at: this.length}, options)); - }, - - // Remove a model from the end of the collection. - pop: function(options) { - var model = this.at(this.length - 1); - return this.remove(model, options); - }, - - // Add a model to the beginning of the collection. - unshift: function(model, options) { - return this.add(model, _.extend({at: 0}, options)); - }, - - // Remove a model from the beginning of the collection. - shift: function(options) { - var model = this.at(0); - return this.remove(model, options); - }, - - // Slice out a sub-array of models from the collection. - slice: function() { - return slice.apply(this.models, arguments); - }, - - // Get a model from the set by id. - get: function(obj) { - if (obj == null) return void 0; - var id = this.modelId(this._isModel(obj) ? obj.attributes : obj); - return this._byId[obj] || this._byId[id] || this._byId[obj.cid]; - }, - - // Get the model at the given index. - at: function(index) { - if (index < 0) index += this.length; - return this.models[index]; - }, - - // Return models with matching attributes. Useful for simple cases of - // `filter`. - where: function(attrs, first) { - var matches = _.matches(attrs); - return this[first ? 'find' : 'filter'](function(model) { - return matches(model.attributes); - }); - }, - - // Return the first model with matching attributes. Useful for simple cases - // of `find`. - findWhere: function(attrs) { - return this.where(attrs, true); - }, - - // Force the collection to re-sort itself. You don't need to call this under - // normal circumstances, as the set will maintain sort order as each item - // is added. - sort: function(options) { - if (!this.comparator) throw new Error('Cannot sort a set without a comparator'); - options || (options = {}); - - // Run sort based on type of `comparator`. - if (_.isString(this.comparator) || this.comparator.length === 1) { - this.models = this.sortBy(this.comparator, this); - } else { - this.models.sort(_.bind(this.comparator, this)); - } - - if (!options.silent) this.trigger('sort', this, options); - return this; - }, - - // Pluck an attribute from each model in the collection. - pluck: function(attr) { - return _.invoke(this.models, 'get', attr); - }, - - // Fetch the default set of models for this collection, resetting the - // collection when they arrive. If `reset: true` is passed, the response - // data will be passed through the `reset` method instead of `set`. - fetch: function(options) { - options = _.extend({parse: true}, options); - var success = options.success; - var collection = this; - options.success = function(resp) { - var method = options.reset ? 'reset' : 'set'; - collection[method](resp, options); - if (success) success.call(options.context, collection, resp, options); - collection.trigger('sync', collection, resp, options); - }; - wrapError(this, options); - return this.sync('read', this, options); - }, - - // Create a new instance of a model in this collection. Add the model to the - // collection immediately, unless `wait: true` is passed, in which case we - // wait for the server to agree. - create: function(model, options) { - options = options ? _.clone(options) : {}; - var wait = options.wait; - model = this._prepareModel(model, options); - if (!model) return false; - if (!wait) this.add(model, options); - var collection = this; - var success = options.success; - options.success = function(model, resp, callbackOpts) { - if (wait) collection.add(model, callbackOpts); - if (success) success.call(callbackOpts.context, model, resp, callbackOpts); - }; - model.save(null, options); - return model; - }, - - // **parse** converts a response into a list of models to be added to the - // collection. The default implementation is just to pass it through. - parse: function(resp, options) { - return resp; - }, - - // Create a new collection with an identical list of models as this one. - clone: function() { - return new this.constructor(this.models, { - model: this.model, - comparator: this.comparator - }); - }, - - // Define how to uniquely identify models in the collection. - modelId: function (attrs) { - return attrs[this.model.prototype.idAttribute || 'id']; - }, - - // Private method to reset all internal state. Called when the collection - // is first initialized or reset. - _reset: function() { - this.length = 0; - this.models = []; - this._byId = {}; - }, - - // Prepare a hash of attributes (or other model) to be added to this - // collection. - _prepareModel: function(attrs, options) { - if (this._isModel(attrs)) { - if (!attrs.collection) attrs.collection = this; - return attrs; - } - options = options ? _.clone(options) : {}; - options.collection = this; - var model = new this.model(attrs, options); - if (!model.validationError) return model; - this.trigger('invalid', this, model.validationError, options); - return false; - }, - - // Internal method called by both remove and set. - // Returns removed models, or false if nothing is removed. - _removeModels: function(models, options) { - var removed = []; - for (var i = 0; i < models.length; i++) { - var model = this.get(models[i]); - if (!model) continue; - - var index = this.indexOf(model); - this.models.splice(index, 1); - this.length--; - - if (!options.silent) { - options.index = index; - model.trigger('remove', model, this, options); - } - - removed.push(model); - this._removeReference(model, options); - } - return removed.length ? removed : false; - }, - - // Method for checking whether an object should be considered a model for - // the purposes of adding to the collection. - _isModel: function (model) { - return model instanceof Model; - }, - - // Internal method to create a model's ties to a collection. - _addReference: function(model, options) { - this._byId[model.cid] = model; - var id = this.modelId(model.attributes); - if (id != null) this._byId[id] = model; - model.on('all', this._onModelEvent, this); - }, - - // Internal method to sever a model's ties to a collection. - _removeReference: function(model, options) { - delete this._byId[model.cid]; - var id = this.modelId(model.attributes); - if (id != null) delete this._byId[id]; - if (this === model.collection) delete model.collection; - model.off('all', this._onModelEvent, this); - }, - - // Internal method called every time a model in the set fires an event. - // Sets need to update their indexes when models change ids. All other - // events simply proxy through. "add" and "remove" events that originate - // in other collections are ignored. - _onModelEvent: function(event, model, collection, options) { - if ((event === 'add' || event === 'remove') && collection !== this) return; - if (event === 'destroy') this.remove(model, options); - if (event === 'change') { - var prevId = this.modelId(model.previousAttributes()); - var id = this.modelId(model.attributes); - if (prevId !== id) { - if (prevId != null) delete this._byId[prevId]; - if (id != null) this._byId[id] = model; - } - } - this.trigger.apply(this, arguments); - } - - }); - - // Underscore methods that we want to implement on the Collection. - // 90% of the core usefulness of Backbone Collections is actually implemented - // right here: - var collectionMethods = { forEach: 3, each: 3, map: 3, collect: 3, reduce: 4, - foldl: 4, inject: 4, reduceRight: 4, foldr: 4, find: 3, detect: 3, filter: 3, - select: 3, reject: 3, every: 3, all: 3, some: 3, any: 3, include: 2, - contains: 2, invoke: 0, max: 3, min: 3, toArray: 1, size: 1, first: 3, - head: 3, take: 3, initial: 3, rest: 3, tail: 3, drop: 3, last: 3, - without: 0, difference: 0, indexOf: 3, shuffle: 1, lastIndexOf: 3, - isEmpty: 1, chain: 1, sample: 3, partition: 3 }; - - // Mix in each Underscore method as a proxy to `Collection#models`. - addUnderscoreMethods(Collection, collectionMethods, 'models'); - - // Underscore methods that take a property name as an argument. - var attributeMethods = ['groupBy', 'countBy', 'sortBy', 'indexBy']; - - // Use attributes instead of properties. - _.each(attributeMethods, function(method) { - if (!_[method]) return; - Collection.prototype[method] = function(value, context) { - var iterator = _.isFunction(value) ? value : function(model) { - return model.get(value); - }; - return _[method](this.models, iterator, context); - }; - }); - - // Backbone.View - // ------------- - - // Backbone Views are almost more convention than they are actual code. A View - // is simply a JavaScript object that represents a logical chunk of UI in the - // DOM. This might be a single item, an entire list, a sidebar or panel, or - // even the surrounding frame which wraps your whole app. Defining a chunk of - // UI as a **View** allows you to define your DOM events declaratively, without - // having to worry about render order ... and makes it easy for the view to - // react to specific changes in the state of your models. - - // Creating a Backbone.View creates its initial element outside of the DOM, - // if an existing element is not provided... - var View = Backbone.View = function(options) { - this.cid = _.uniqueId('view'); - _.extend(this, _.pick(options, viewOptions)); - this._ensureElement(); - this.initialize.apply(this, arguments); - }; - - // Cached regex to split keys for `delegate`. - var delegateEventSplitter = /^(\S+)\s*(.*)$/; - - // List of view options to be merged as properties. - var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events']; - - // Set up all inheritable **Backbone.View** properties and methods. - _.extend(View.prototype, Events, { - - // The default `tagName` of a View's element is `"div"`. - tagName: 'div', - - // jQuery delegate for element lookup, scoped to DOM elements within the - // current view. This should be preferred to global lookups where possible. - $: function(selector) { - return this.$el.find(selector); - }, - - // Initialize is an empty function by default. Override it with your own - // initialization logic. - initialize: function(){}, - - // **render** is the core function that your view should override, in order - // to populate its element (`this.el`), with the appropriate HTML. The - // convention is for **render** to always return `this`. - render: function() { - return this; - }, - - // Remove this view by taking the element out of the DOM, and removing any - // applicable Backbone.Events listeners. - remove: function() { - this._removeElement(); - this.stopListening(); - return this; - }, - - // Remove this view's element from the document and all event listeners - // attached to it. Exposed for subclasses using an alternative DOM - // manipulation API. - _removeElement: function() { - this.$el.remove(); - }, - - // Change the view's element (`this.el` property) and re-delegate the - // view's events on the new element. - setElement: function(element) { - this.undelegateEvents(); - this._setElement(element); - this.delegateEvents(); - return this; - }, - - // Creates the `this.el` and `this.$el` references for this view using the - // given `el`. `el` can be a CSS selector or an HTML string, a jQuery - // context or an element. Subclasses can override this to utilize an - // alternative DOM manipulation API and are only required to set the - // `this.el` property. - _setElement: function(el) { - this.$el = el instanceof Backbone.$ ? el : Backbone.$(el); - this.el = this.$el[0]; - }, - - // Set callbacks, where `this.events` is a hash of - // - // *{"event selector": "callback"}* - // - // { - // 'mousedown .title': 'edit', - // 'click .button': 'save', - // 'click .open': function(e) { ... } - // } - // - // pairs. Callbacks will be bound to the view, with `this` set properly. - // Uses event delegation for efficiency. - // Omitting the selector binds the event to `this.el`. - delegateEvents: function(events) { - events || (events = _.result(this, 'events')); - if (!events) return this; - this.undelegateEvents(); - for (var key in events) { - var method = events[key]; - if (!_.isFunction(method)) method = this[method]; - if (!method) continue; - var match = key.match(delegateEventSplitter); - this.delegate(match[1], match[2], _.bind(method, this)); - } - return this; - }, - - // Add a single event listener to the view's element (or a child element - // using `selector`). This only works for delegate-able events: not `focus`, - // `blur`, and not `change`, `submit`, and `reset` in Internet Explorer. - delegate: function(eventName, selector, listener) { - this.$el.on(eventName + '.delegateEvents' + this.cid, selector, listener); - return this; - }, - - // Clears all callbacks previously bound to the view by `delegateEvents`. - // You usually don't need to use this, but may wish to if you have multiple - // Backbone views attached to the same DOM element. - undelegateEvents: function() { - if (this.$el) this.$el.off('.delegateEvents' + this.cid); - return this; - }, - - // A finer-grained `undelegateEvents` for removing a single delegated event. - // `selector` and `listener` are both optional. - undelegate: function(eventName, selector, listener) { - this.$el.off(eventName + '.delegateEvents' + this.cid, selector, listener); - return this; - }, - - // Produces a DOM element to be assigned to your view. Exposed for - // subclasses using an alternative DOM manipulation API. - _createElement: function(tagName) { - return document.createElement(tagName); - }, - - // Ensure that the View has a DOM element to render into. - // If `this.el` is a string, pass it through `$()`, take the first - // matching element, and re-assign it to `el`. Otherwise, create - // an element from the `id`, `className` and `tagName` properties. - _ensureElement: function() { - if (!this.el) { - var attrs = _.extend({}, _.result(this, 'attributes')); - if (this.id) attrs.id = _.result(this, 'id'); - if (this.className) attrs['class'] = _.result(this, 'className'); - this.setElement(this._createElement(_.result(this, 'tagName'))); - this._setAttributes(attrs); - } else { - this.setElement(_.result(this, 'el')); - } - }, - - // Set attributes from a hash on this view's element. Exposed for - // subclasses using an alternative DOM manipulation API. - _setAttributes: function(attributes) { - this.$el.attr(attributes); - } - - }); - - // Backbone.sync - // ------------- - - // Override this function to change the manner in which Backbone persists - // models to the server. You will be passed the type of request, and the - // model in question. By default, makes a RESTful Ajax request - // to the model's `url()`. Some possible customizations could be: - // - // * Use `setTimeout` to batch rapid-fire updates into a single request. - // * Send up the models as XML instead of JSON. - // * Persist models via WebSockets instead of Ajax. - // - // Turn on `Backbone.emulateHTTP` in order to send `PUT` and `DELETE` requests - // as `POST`, with a `_method` parameter containing the true HTTP method, - // as well as all requests with the body as `application/x-www-form-urlencoded` - // instead of `application/json` with the model in a param named `model`. - // Useful when interfacing with server-side languages like **PHP** that make - // it difficult to read the body of `PUT` requests. - Backbone.sync = function(method, model, options) { - var type = methodMap[method]; - - // Default options, unless specified. - _.defaults(options || (options = {}), { - emulateHTTP: Backbone.emulateHTTP, - emulateJSON: Backbone.emulateJSON - }); - - // Default JSON-request options. - var params = {type: type, dataType: 'json'}; - - // Ensure that we have a URL. - if (!options.url) { - params.url = _.result(model, 'url') || urlError(); - } - - // Ensure that we have the appropriate request data. - if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) { - params.contentType = 'application/json'; - params.data = JSON.stringify(options.attrs || model.toJSON(options)); - } - - // For older servers, emulate JSON by encoding the request into an HTML-form. - if (options.emulateJSON) { - params.contentType = 'application/x-www-form-urlencoded'; - params.data = params.data ? {model: params.data} : {}; - } - - // For older servers, emulate HTTP by mimicking the HTTP method with `_method` - // And an `X-HTTP-Method-Override` header. - if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) { - params.type = 'POST'; - if (options.emulateJSON) params.data._method = type; - var beforeSend = options.beforeSend; - options.beforeSend = function(xhr) { - xhr.setRequestHeader('X-HTTP-Method-Override', type); - if (beforeSend) return beforeSend.apply(this, arguments); - }; - } - - // Don't process data on a non-GET request. - if (params.type !== 'GET' && !options.emulateJSON) { - params.processData = false; - } - - // Pass along `textStatus` and `errorThrown` from jQuery. - var error = options.error; - options.error = function(xhr, textStatus, errorThrown) { - options.textStatus = textStatus; - options.errorThrown = errorThrown; - if (error) error.call(options.context, xhr, textStatus, errorThrown); - }; - - // Make the request, allowing the user to override any Ajax options. - var xhr = options.xhr = Backbone.ajax(_.extend(params, options)); - model.trigger('request', model, xhr, options); - return xhr; - }; - - // Map from CRUD to HTTP for our default `Backbone.sync` implementation. - var methodMap = { - 'create': 'POST', - 'update': 'PUT', - 'patch': 'PATCH', - 'delete': 'DELETE', - 'read': 'GET' - }; - - // Set the default implementation of `Backbone.ajax` to proxy through to `$`. - // Override this if you'd like to use a different library. - Backbone.ajax = function() { - return Backbone.$.ajax.apply(Backbone.$, arguments); - }; - - // Backbone.Router - // --------------- - - // Routers map faux-URLs to actions, and fire events when routes are - // matched. Creating a new one sets its `routes` hash, if not set statically. - var Router = Backbone.Router = function(options) { - options || (options = {}); - if (options.routes) this.routes = options.routes; - this._bindRoutes(); - this.initialize.apply(this, arguments); - }; - - // Cached regular expressions for matching named param parts and splatted - // parts of route strings. - var optionalParam = /\((.*?)\)/g; - var namedParam = /(\(\?)?:\w+/g; - var splatParam = /\*\w+/g; - var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g; - - // Set up all inheritable **Backbone.Router** properties and methods. - _.extend(Router.prototype, Events, { - - // Initialize is an empty function by default. Override it with your own - // initialization logic. - initialize: function(){}, - - // Manually bind a single named route to a callback. For example: - // - // this.route('search/:query/p:num', 'search', function(query, num) { - // ... - // }); - // - route: function(route, name, callback) { - if (!_.isRegExp(route)) route = this._routeToRegExp(route); - if (_.isFunction(name)) { - callback = name; - name = ''; - } - if (!callback) callback = this[name]; - var router = this; - Backbone.history.route(route, function(fragment) { - var args = router._extractParameters(route, fragment); - if (router.execute(callback, args, name) !== false) { - router.trigger.apply(router, ['route:' + name].concat(args)); - router.trigger('route', name, args); - Backbone.history.trigger('route', router, name, args); - } - }); - return this; - }, - - // Execute a route handler with the provided parameters. This is an - // excellent place to do pre-route setup or post-route cleanup. - execute: function(callback, args, name) { - if (callback) callback.apply(this, args); - }, - - // Simple proxy to `Backbone.history` to save a fragment into the history. - navigate: function(fragment, options) { - Backbone.history.navigate(fragment, options); - return this; - }, - - // Bind all defined routes to `Backbone.history`. We have to reverse the - // order of the routes here to support behavior where the most general - // routes can be defined at the bottom of the route map. - _bindRoutes: function() { - if (!this.routes) return; - this.routes = _.result(this, 'routes'); - var route, routes = _.keys(this.routes); - while ((route = routes.pop()) != null) { - this.route(route, this.routes[route]); - } - }, - - // Convert a route string into a regular expression, suitable for matching - // against the current location hash. - _routeToRegExp: function(route) { - route = route.replace(escapeRegExp, '\\$&') - .replace(optionalParam, '(?:$1)?') - .replace(namedParam, function(match, optional) { - return optional ? match : '([^/?]+)'; - }) - .replace(splatParam, '([^?]*?)'); - return new RegExp('^' + route + '(?:\\?([\\s\\S]*))?$'); - }, - - // Given a route, and a URL fragment that it matches, return the array of - // extracted decoded parameters. Empty or unmatched parameters will be - // treated as `null` to normalize cross-browser behavior. - _extractParameters: function(route, fragment) { - var params = route.exec(fragment).slice(1); - return _.map(params, function(param, i) { - // Don't decode the search params. - if (i === params.length - 1) return param || null; - return param ? decodeURIComponent(param) : null; - }); - } - - }); - - // Backbone.History - // ---------------- - - // Handles cross-browser history management, based on either - // [pushState](http://diveintohtml5.info/history.html) and real URLs, or - // [onhashchange](https://developer.mozilla.org/en-US/docs/DOM/window.onhashchange) - // and URL fragments. If the browser supports neither (old IE, natch), - // falls back to polling. - var History = Backbone.History = function() { - this.handlers = []; - _.bindAll(this, 'checkUrl'); - - // Ensure that `History` can be used outside of the browser. - if (typeof window !== 'undefined') { - this.location = window.location; - this.history = window.history; - } - }; - - // Cached regex for stripping a leading hash/slash and trailing space. - var routeStripper = /^[#\/]|\s+$/g; - - // Cached regex for stripping leading and trailing slashes. - var rootStripper = /^\/+|\/+$/g; - - // Cached regex for stripping urls of hash. - var pathStripper = /#.*$/; - - // Has the history handling already been started? - History.started = false; - - // Set up all inheritable **Backbone.History** properties and methods. - _.extend(History.prototype, Events, { - - // The default interval to poll for hash changes, if necessary, is - // twenty times a second. - interval: 50, - - // Are we at the app root? - atRoot: function() { - var path = this.location.pathname.replace(/[^\/]$/, '$&/'); - return path === this.root && !this.getSearch(); - }, - - // Does the pathname match the root? - matchRoot: function() { - var path = this.decodeFragment(this.location.pathname); - var root = path.slice(0, this.root.length - 1) + '/'; - return root === this.root; - }, - - // Unicode characters in `location.pathname` are percent encoded so they're - // decoded for comparison. `%25` should not be decoded since it may be part - // of an encoded parameter. - decodeFragment: function(fragment) { - return decodeURI(fragment.replace(/%25/g, '%2525')); - }, - - // In IE6, the hash fragment and search params are incorrect if the - // fragment contains `?`. - getSearch: function() { - var match = this.location.href.replace(/#.*/, '').match(/\?.+/); - return match ? match[0] : ''; - }, - - // Gets the true hash value. Cannot use location.hash directly due to bug - // in Firefox where location.hash will always be decoded. - getHash: function(window) { - var match = (window || this).location.href.match(/#(.*)$/); - return match ? match[1] : ''; - }, - - // Get the pathname and search params, without the root. - getPath: function() { - var path = this.decodeFragment( - this.location.pathname + this.getSearch() - ).slice(this.root.length - 1); - return path.charAt(0) === '/' ? path.slice(1) : path; - }, - - // Get the cross-browser normalized URL fragment from the path or hash. - getFragment: function(fragment) { - if (fragment == null) { - if (this._usePushState || !this._wantsHashChange) { - fragment = this.getPath(); - } else { - fragment = this.getHash(); - } - } - return fragment.replace(routeStripper, ''); - }, - - // Start the hash change handling, returning `true` if the current URL matches - // an existing route, and `false` otherwise. - start: function(options) { - if (History.started) throw new Error('Backbone.history has already been started'); - History.started = true; - - // Figure out the initial configuration. Do we need an iframe? - // Is pushState desired ... is it available? - this.options = _.extend({root: '/'}, this.options, options); - this.root = this.options.root; - this._wantsHashChange = this.options.hashChange !== false; - this._hasHashChange = 'onhashchange' in window; - this._useHashChange = this._wantsHashChange && this._hasHashChange; - this._wantsPushState = !!this.options.pushState; - this._hasPushState = !!(this.history && this.history.pushState); - this._usePushState = this._wantsPushState && this._hasPushState; - this.fragment = this.getFragment(); - - // Normalize root to always include a leading and trailing slash. - this.root = ('/' + this.root + '/').replace(rootStripper, '/'); - - // Transition from hashChange to pushState or vice versa if both are - // requested. - if (this._wantsHashChange && this._wantsPushState) { - - // If we've started off with a route from a `pushState`-enabled - // browser, but we're currently in a browser that doesn't support it... - if (!this._hasPushState && !this.atRoot()) { - var root = this.root.slice(0, -1) || '/'; - this.location.replace(root + '#' + this.getPath()); - // Return immediately as browser will do redirect to new url - return true; - - // Or if we've started out with a hash-based route, but we're currently - // in a browser where it could be `pushState`-based instead... - } else if (this._hasPushState && this.atRoot()) { - this.navigate(this.getHash(), {replace: true}); - } - - } - - // Proxy an iframe to handle location events if the browser doesn't - // support the `hashchange` event, HTML5 history, or the user wants - // `hashChange` but not `pushState`. - if (!this._hasHashChange && this._wantsHashChange && !this._usePushState) { - this.iframe = document.createElement('iframe'); - this.iframe.src = 'javascript:0'; - this.iframe.style.display = 'none'; - this.iframe.tabIndex = -1; - var body = document.body; - // Using `appendChild` will throw on IE < 9 if the document is not ready. - var iWindow = body.insertBefore(this.iframe, body.firstChild).contentWindow; - iWindow.document.open(); - iWindow.document.close(); - iWindow.location.hash = '#' + this.fragment; - } - - // Add a cross-platform `addEventListener` shim for older browsers. - var addEventListener = window.addEventListener || function (eventName, listener) { - return attachEvent('on' + eventName, listener); - }; - - // Depending on whether we're using pushState or hashes, and whether - // 'onhashchange' is supported, determine how we check the URL state. - if (this._usePushState) { - addEventListener('popstate', this.checkUrl, false); - } else if (this._useHashChange && !this.iframe) { - addEventListener('hashchange', this.checkUrl, false); - } else if (this._wantsHashChange) { - this._checkUrlInterval = setInterval(this.checkUrl, this.interval); - } - - if (!this.options.silent) return this.loadUrl(); - }, - - // Disable Backbone.history, perhaps temporarily. Not useful in a real app, - // but possibly useful for unit testing Routers. - stop: function() { - // Add a cross-platform `removeEventListener` shim for older browsers. - var removeEventListener = window.removeEventListener || function (eventName, listener) { - return detachEvent('on' + eventName, listener); - }; - - // Remove window listeners. - if (this._usePushState) { - removeEventListener('popstate', this.checkUrl, false); - } else if (this._useHashChange && !this.iframe) { - removeEventListener('hashchange', this.checkUrl, false); - } - - // Clean up the iframe if necessary. - if (this.iframe) { - document.body.removeChild(this.iframe); - this.iframe = null; - } - - // Some environments will throw when clearing an undefined interval. - if (this._checkUrlInterval) clearInterval(this._checkUrlInterval); - History.started = false; - }, - - // Add a route to be tested when the fragment changes. Routes added later - // may override previous routes. - route: function(route, callback) { - this.handlers.unshift({route: route, callback: callback}); - }, - - // Checks the current URL to see if it has changed, and if it has, - // calls `loadUrl`, normalizing across the hidden iframe. - checkUrl: function(e) { - var current = this.getFragment(); - - // If the user pressed the back button, the iframe's hash will have - // changed and we should use that for comparison. - if (current === this.fragment && this.iframe) { - current = this.getHash(this.iframe.contentWindow); - } - - if (current === this.fragment) return false; - if (this.iframe) this.navigate(current); - this.loadUrl(); - }, - - // Attempt to load the current URL fragment. If a route succeeds with a - // match, returns `true`. If no defined routes matches the fragment, - // returns `false`. - loadUrl: function(fragment) { - // If the root doesn't match, no routes can match either. - if (!this.matchRoot()) return false; - fragment = this.fragment = this.getFragment(fragment); - return _.any(this.handlers, function(handler) { - if (handler.route.test(fragment)) { - handler.callback(fragment); - return true; - } - }); - }, - - // Save a fragment into the hash history, or replace the URL state if the - // 'replace' option is passed. You are responsible for properly URL-encoding - // the fragment in advance. - // - // The options object can contain `trigger: true` if you wish to have the - // route callback be fired (not usually desirable), or `replace: true`, if - // you wish to modify the current URL without adding an entry to the history. - navigate: function(fragment, options) { - if (!History.started) return false; - if (!options || options === true) options = {trigger: !!options}; - - // Normalize the fragment. - fragment = this.getFragment(fragment || ''); - - // Don't include a trailing slash on the root. - var root = this.root; - if (fragment === '' || fragment.charAt(0) === '?') { - root = root.slice(0, -1) || '/'; - } - var url = root + fragment; - - // Strip the hash and decode for matching. - fragment = this.decodeFragment(fragment.replace(pathStripper, '')); - - if (this.fragment === fragment) return; - this.fragment = fragment; - - // If pushState is available, we use it to set the fragment as a real URL. - if (this._usePushState) { - this.history[options.replace ? 'replaceState' : 'pushState']({}, document.title, url); - - // If hash changes haven't been explicitly disabled, update the hash - // fragment to store history. - } else if (this._wantsHashChange) { - this._updateHash(this.location, fragment, options.replace); - if (this.iframe && (fragment !== this.getHash(this.iframe.contentWindow))) { - var iWindow = this.iframe.contentWindow; - - // Opening and closing the iframe tricks IE7 and earlier to push a - // history entry on hash-tag change. When replace is true, we don't - // want this. - if (!options.replace) { - iWindow.document.open(); - iWindow.document.close(); - } - - this._updateHash(iWindow.location, fragment, options.replace); - } - - // If you've told us that you explicitly don't want fallback hashchange- - // based history, then `navigate` becomes a page refresh. - } else { - return this.location.assign(url); - } - if (options.trigger) return this.loadUrl(fragment); - }, - - // Update the hash location, either replacing the current entry, or adding - // a new one to the browser history. - _updateHash: function(location, fragment, replace) { - if (replace) { - var href = location.href.replace(/(javascript:|#).*$/, ''); - location.replace(href + '#' + fragment); - } else { - // Some browsers require that `hash` contains a leading #. - location.hash = '#' + fragment; - } - } - - }); - - // Create the default Backbone.history. - Backbone.history = new History; - - // Helpers - // ------- - - // Helper function to correctly set up the prototype chain for subclasses. - // Similar to `goog.inherits`, but uses a hash of prototype properties and - // class properties to be extended. - var extend = function(protoProps, staticProps) { - var parent = this; - var child; - - // The constructor function for the new subclass is either defined by you - // (the "constructor" property in your `extend` definition), or defaulted - // by us to simply call the parent constructor. - if (protoProps && _.has(protoProps, 'constructor')) { - child = protoProps.constructor; - } else { - child = function(){ return parent.apply(this, arguments); }; - } - - // Add static properties to the constructor function, if supplied. - _.extend(child, parent, staticProps); - - // Set the prototype chain to inherit from `parent`, without calling - // `parent` constructor function. - var Surrogate = function(){ this.constructor = child; }; - Surrogate.prototype = parent.prototype; - child.prototype = new Surrogate; - - // Add prototype properties (instance properties) to the subclass, - // if supplied. - if (protoProps) _.extend(child.prototype, protoProps); - - // Set a convenience property in case the parent's prototype is needed - // later. - child.__super__ = parent.prototype; - - return child; - }; - - // Set up inheritance for the model, collection, router, view and history. - Model.extend = Collection.extend = Router.extend = View.extend = History.extend = extend; - - // Throw an error when a URL is needed, and none is supplied. - var urlError = function() { - throw new Error('A "url" property or function must be specified'); - }; - - // Wrap an optional error callback with a fallback error event. - var wrapError = function(model, options) { - var error = options.error; - options.error = function(resp) { - if (error) error.call(options.context, model, resp, options); - model.trigger('error', model, resp, options); - }; - }; - - return Backbone; - -})); + // Establish the root object, `window` (`self`) in the browser, or `global` on the server. + // We use `self` instead of `window` for `WebWorker` support. + var root = typeof self == 'object' && self.self === self && self || + typeof global == 'object' && global.global === global && global; + + // Set up Backbone appropriately for the environment. Start with AMD. + if (typeof define === 'function' && define.amd) { + define(['underscore', 'jquery', 'exports'], function(_, $, exports) { + // Export global even in AMD case in case this script is loaded with + // others that may still expect a global Backbone. + root.Backbone = factory(root, exports, _, $); + }); + + // Next for Node.js or CommonJS. jQuery may not be needed as a module. + } else if (typeof exports !== 'undefined') { + var _ = require('underscore'), $; + try { $ = require('jquery'); } catch (e) {} + factory(root, exports, _, $); + + // Finally, as a browser global. + } else { + root.Backbone = factory(root, {}, root._, root.jQuery || root.Zepto || root.ender || root.$); + } + +})(function(root, Backbone, _, $) { + + // Initial Setup + // ------------- + + // Save the previous value of the `Backbone` variable, so that it can be + // restored later on, if `noConflict` is used. + var previousBackbone = root.Backbone; + + // Create a local reference to a common array method we'll want to use later. + var slice = Array.prototype.slice; + + // Current version of the library. Keep in sync with `package.json`. + Backbone.VERSION = '1.4.0'; + + // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns + // the `$` variable. + Backbone.$ = $; + + // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable + // to its previous owner. Returns a reference to this Backbone object. + Backbone.noConflict = function() { + root.Backbone = previousBackbone; + return this; + }; + + // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option + // will fake `"PATCH"`, `"PUT"` and `"DELETE"` requests via the `_method` parameter and + // set a `X-Http-Method-Override` header. + Backbone.emulateHTTP = false; + + // Turn on `emulateJSON` to support legacy servers that can't deal with direct + // `application/json` requests ... this will encode the body as + // `application/x-www-form-urlencoded` instead and will send the model in a + // form param named `model`. + Backbone.emulateJSON = false; + + // Backbone.Events + // --------------- + + // A module that can be mixed in to *any object* in order to provide it with + // a custom event channel. You may bind a callback to an event with `on` or + // remove with `off`; `trigger`-ing an event fires all callbacks in + // succession. + // + // var object = {}; + // _.extend(object, Backbone.Events); + // object.on('expand', function(){ alert('expanded'); }); + // object.trigger('expand'); + // + var Events = Backbone.Events = {}; + + // Regular expression used to split event strings. + var eventSplitter = /\s+/; + + // A private global variable to share between listeners and listenees. + var _listening; + + // Iterates over the standard `event, callback` (as well as the fancy multiple + // space-separated events `"change blur", callback` and jQuery-style event + // maps `{event: callback}`). + var eventsApi = function(iteratee, events, name, callback, opts) { + var i = 0, names; + if (name && typeof name === 'object') { + // Handle event maps. + if (callback !== void 0 && 'context' in opts && opts.context === void 0) opts.context = callback; + for (names = _.keys(name); i < names.length ; i++) { + events = eventsApi(iteratee, events, names[i], name[names[i]], opts); + } + } else if (name && eventSplitter.test(name)) { + // Handle space-separated event names by delegating them individually. + for (names = name.split(eventSplitter); i < names.length; i++) { + events = iteratee(events, names[i], callback, opts); + } + } else { + // Finally, standard events. + events = iteratee(events, name, callback, opts); + } + return events; + }; + + // Bind an event to a `callback` function. Passing `"all"` will bind + // the callback to all events fired. + Events.on = function(name, callback, context) { + this._events = eventsApi(onApi, this._events || {}, name, callback, { + context: context, + ctx: this, + listening: _listening + }); + + if (_listening) { + var listeners = this._listeners || (this._listeners = {}); + listeners[_listening.id] = _listening; + // Allow the listening to use a counter, instead of tracking + // callbacks for library interop + _listening.interop = false; + } + + return this; + }; + + // Inversion-of-control versions of `on`. Tell *this* object to listen to + // an event in another object... keeping track of what it's listening to + // for easier unbinding later. + Events.listenTo = function(obj, name, callback) { + if (!obj) return this; + var id = obj._listenId || (obj._listenId = _.uniqueId('l')); + var listeningTo = this._listeningTo || (this._listeningTo = {}); + var listening = _listening = listeningTo[id]; + + // This object is not listening to any other events on `obj` yet. + // Setup the necessary references to track the listening callbacks. + if (!listening) { + this._listenId || (this._listenId = _.uniqueId('l')); + listening = _listening = listeningTo[id] = new Listening(this, obj); + } + + // Bind callbacks on obj. + var error = tryCatchOn(obj, name, callback, this); + _listening = void 0; + + if (error) throw error; + // If the target obj is not Backbone.Events, track events manually. + if (listening.interop) listening.on(name, callback); + + return this; + }; + + // The reducing API that adds a callback to the `events` object. + var onApi = function(events, name, callback, options) { + if (callback) { + var handlers = events[name] || (events[name] = []); + var context = options.context, ctx = options.ctx, listening = options.listening; + if (listening) listening.count++; + + handlers.push({callback: callback, context: context, ctx: context || ctx, listening: listening}); + } + return events; + }; + + // An try-catch guarded #on function, to prevent poisoning the global + // `_listening` variable. + var tryCatchOn = function(obj, name, callback, context) { + try { + obj.on(name, callback, context); + } catch (e) { + return e; + } + }; + + // Remove one or many callbacks. If `context` is null, removes all + // callbacks with that function. If `callback` is null, removes all + // callbacks for the event. If `name` is null, removes all bound + // callbacks for all events. + Events.off = function(name, callback, context) { + if (!this._events) return this; + this._events = eventsApi(offApi, this._events, name, callback, { + context: context, + listeners: this._listeners + }); + + return this; + }; + + // Tell this object to stop listening to either specific events ... or + // to every object it's currently listening to. + Events.stopListening = function(obj, name, callback) { + var listeningTo = this._listeningTo; + if (!listeningTo) return this; + + var ids = obj ? [obj._listenId] : _.keys(listeningTo); + for (var i = 0; i < ids.length; i++) { + var listening = listeningTo[ids[i]]; + + // If listening doesn't exist, this object is not currently + // listening to obj. Break out early. + if (!listening) break; + + listening.obj.off(name, callback, this); + if (listening.interop) listening.off(name, callback); + } + if (_.isEmpty(listeningTo)) this._listeningTo = void 0; + + return this; + }; + + // The reducing API that removes a callback from the `events` object. + var offApi = function(events, name, callback, options) { + if (!events) return; + + var context = options.context, listeners = options.listeners; + var i = 0, names; + + // Delete all event listeners and "drop" events. + if (!name && !context && !callback) { + for (names = _.keys(listeners); i < names.length; i++) { + listeners[names[i]].cleanup(); + } + return; + } + + names = name ? [name] : _.keys(events); + for (; i < names.length; i++) { + name = names[i]; + var handlers = events[name]; + + // Bail out if there are no events stored. + if (!handlers) break; + + // Find any remaining events. + var remaining = []; + for (var j = 0; j < handlers.length; j++) { + var handler = handlers[j]; + if ( + callback && callback !== handler.callback && + callback !== handler.callback._callback || + context && context !== handler.context + ) { + remaining.push(handler); + } else { + var listening = handler.listening; + if (listening) listening.off(name, callback); + } + } + + // Replace events if there are any remaining. Otherwise, clean up. + if (remaining.length) { + events[name] = remaining; + } else { + delete events[name]; + } + } + + return events; + }; + + // Bind an event to only be triggered a single time. After the first time + // the callback is invoked, its listener will be removed. If multiple events + // are passed in using the space-separated syntax, the handler will fire + // once for each event, not once for a combination of all events. + Events.once = function(name, callback, context) { + // Map the event into a `{event: once}` object. + var events = eventsApi(onceMap, {}, name, callback, this.off.bind(this)); + if (typeof name === 'string' && context == null) callback = void 0; + return this.on(events, callback, context); + }; + + // Inversion-of-control versions of `once`. + Events.listenToOnce = function(obj, name, callback) { + // Map the event into a `{event: once}` object. + var events = eventsApi(onceMap, {}, name, callback, this.stopListening.bind(this, obj)); + return this.listenTo(obj, events); + }; + + // Reduces the event callbacks into a map of `{event: onceWrapper}`. + // `offer` unbinds the `onceWrapper` after it has been called. + var onceMap = function(map, name, callback, offer) { + if (callback) { + var once = map[name] = _.once(function() { + offer(name, once); + callback.apply(this, arguments); + }); + once._callback = callback; + } + return map; + }; + + // Trigger one or many events, firing all bound callbacks. Callbacks are + // passed the same arguments as `trigger` is, apart from the event name + // (unless you're listening on `"all"`, which will cause your callback to + // receive the true name of the event as the first argument). + Events.trigger = function(name) { + if (!this._events) return this; + + var length = Math.max(0, arguments.length - 1); + var args = Array(length); + for (var i = 0; i < length; i++) args[i] = arguments[i + 1]; + + eventsApi(triggerApi, this._events, name, void 0, args); + return this; + }; + + // Handles triggering the appropriate event callbacks. + var triggerApi = function(objEvents, name, callback, args) { + if (objEvents) { + var events = objEvents[name]; + var allEvents = objEvents.all; + if (events && allEvents) allEvents = allEvents.slice(); + if (events) triggerEvents(events, args); + if (allEvents) triggerEvents(allEvents, [name].concat(args)); + } + return objEvents; + }; + + // A difficult-to-believe, but optimized internal dispatch function for + // triggering events. Tries to keep the usual cases speedy (most internal + // Backbone events have 3 arguments). + var triggerEvents = function(events, args) { + var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2]; + switch (args.length) { + case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return; + case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return; + case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return; + case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return; + default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); return; + } + }; + + // A listening class that tracks and cleans up memory bindings + // when all callbacks have been offed. + var Listening = function(listener, obj) { + this.id = listener._listenId; + this.listener = listener; + this.obj = obj; + this.interop = true; + this.count = 0; + this._events = void 0; + }; + + Listening.prototype.on = Events.on; + + // Offs a callback (or several). + // Uses an optimized counter if the listenee uses Backbone.Events. + // Otherwise, falls back to manual tracking to support events + // library interop. + Listening.prototype.off = function(name, callback) { + var cleanup; + if (this.interop) { + this._events = eventsApi(offApi, this._events, name, callback, { + context: void 0, + listeners: void 0 + }); + cleanup = !this._events; + } else { + this.count--; + cleanup = this.count === 0; + } + if (cleanup) this.cleanup(); + }; + + // Cleans up memory bindings between the listener and the listenee. + Listening.prototype.cleanup = function() { + delete this.listener._listeningTo[this.obj._listenId]; + if (!this.interop) delete this.obj._listeners[this.id]; + }; + + // Aliases for backwards compatibility. + Events.bind = Events.on; + Events.unbind = Events.off; + + // Allow the `Backbone` object to serve as a global event bus, for folks who + // want global "pubsub" in a convenient place. + _.extend(Backbone, Events); + + // Backbone.Model + // -------------- + + // Backbone **Models** are the basic data object in the framework -- + // frequently representing a row in a table in a database on your server. + // A discrete chunk of data and a bunch of useful, related methods for + // performing computations and transformations on that data. + + // Create a new model with the specified attributes. A client id (`cid`) + // is automatically generated and assigned for you. + var Model = Backbone.Model = function(attributes, options) { + var attrs = attributes || {}; + options || (options = {}); + this.preinitialize.apply(this, arguments); + this.cid = _.uniqueId(this.cidPrefix); + this.attributes = {}; + if (options.collection) this.collection = options.collection; + if (options.parse) attrs = this.parse(attrs, options) || {}; + var defaults = _.result(this, 'defaults'); + attrs = _.defaults(_.extend({}, defaults, attrs), defaults); + this.set(attrs, options); + this.changed = {}; + this.initialize.apply(this, arguments); + }; + + // Attach all inheritable methods to the Model prototype. + _.extend(Model.prototype, Events, { + + // A hash of attributes whose current and previous value differ. + changed: null, + + // The value returned during the last failed validation. + validationError: null, + + // The default name for the JSON `id` attribute is `"id"`. MongoDB and + // CouchDB users may want to set this to `"_id"`. + idAttribute: 'id', + + // The prefix is used to create the client id which is used to identify models locally. + // You may want to override this if you're experiencing name clashes with model ids. + cidPrefix: 'c', + + // preinitialize is an empty function by default. You can override it with a function + // or object. preinitialize will run before any instantiation logic is run in the Model. + preinitialize: function(){}, + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize: function(){}, + + // Return a copy of the model's `attributes` object. + toJSON: function(options) { + return _.clone(this.attributes); + }, + + // Proxy `Backbone.sync` by default -- but override this if you need + // custom syncing semantics for *this* particular model. + sync: function() { + return Backbone.sync.apply(this, arguments); + }, + + // Get the value of an attribute. + get: function(attr) { + return this.attributes[attr]; + }, + + // Get the HTML-escaped value of an attribute. + escape: function(attr) { + return _.escape(this.get(attr)); + }, + + // Returns `true` if the attribute contains a value that is not null + // or undefined. + has: function(attr) { + return this.get(attr) != null; + }, + + // Special-cased proxy to underscore's `_.matches` method. + matches: function(attrs) { + return !!_.iteratee(attrs, this)(this.attributes); + }, + + // Set a hash of model attributes on the object, firing `"change"`. This is + // the core primitive operation of a model, updating the data and notifying + // anyone who needs to know about the change in state. The heart of the beast. + set: function(key, val, options) { + if (key == null) return this; + + // Handle both `"key", value` and `{key: value}` -style arguments. + var attrs; + if (typeof key === 'object') { + attrs = key; + options = val; + } else { + (attrs = {})[key] = val; + } + + options || (options = {}); + + // Run validation. + if (!this._validate(attrs, options)) return false; + + // Extract attributes and options. + var unset = options.unset; + var silent = options.silent; + var changes = []; + var changing = this._changing; + this._changing = true; + + if (!changing) { + this._previousAttributes = _.clone(this.attributes); + this.changed = {}; + } + + var current = this.attributes; + var changed = this.changed; + var prev = this._previousAttributes; + + // For each `set` attribute, update or delete the current value. + for (var attr in attrs) { + val = attrs[attr]; + if (!_.isEqual(current[attr], val)) changes.push(attr); + if (!_.isEqual(prev[attr], val)) { + changed[attr] = val; + } else { + delete changed[attr]; + } + unset ? delete current[attr] : current[attr] = val; + } + + // Update the `id`. + if (this.idAttribute in attrs) this.id = this.get(this.idAttribute); + + // Trigger all relevant attribute changes. + if (!silent) { + if (changes.length) this._pending = options; + for (var i = 0; i < changes.length; i++) { + this.trigger('change:' + changes[i], this, current[changes[i]], options); + } + } + + // You might be wondering why there's a `while` loop here. Changes can + // be recursively nested within `"change"` events. + if (changing) return this; + if (!silent) { + while (this._pending) { + options = this._pending; + this._pending = false; + this.trigger('change', this, options); + } + } + this._pending = false; + this._changing = false; + return this; + }, + + // Remove an attribute from the model, firing `"change"`. `unset` is a noop + // if the attribute doesn't exist. + unset: function(attr, options) { + return this.set(attr, void 0, _.extend({}, options, {unset: true})); + }, + + // Clear all attributes on the model, firing `"change"`. + clear: function(options) { + var attrs = {}; + for (var key in this.attributes) attrs[key] = void 0; + return this.set(attrs, _.extend({}, options, {unset: true})); + }, + + // Determine if the model has changed since the last `"change"` event. + // If you specify an attribute name, determine if that attribute has changed. + hasChanged: function(attr) { + if (attr == null) return !_.isEmpty(this.changed); + return _.has(this.changed, attr); + }, + + // Return an object containing all the attributes that have changed, or + // false if there are no changed attributes. Useful for determining what + // parts of a view need to be updated and/or what attributes need to be + // persisted to the server. Unset attributes will be set to undefined. + // You can also pass an attributes object to diff against the model, + // determining if there *would be* a change. + changedAttributes: function(diff) { + if (!diff) return this.hasChanged() ? _.clone(this.changed) : false; + var old = this._changing ? this._previousAttributes : this.attributes; + var changed = {}; + var hasChanged; + for (var attr in diff) { + var val = diff[attr]; + if (_.isEqual(old[attr], val)) continue; + changed[attr] = val; + hasChanged = true; + } + return hasChanged ? changed : false; + }, + + // Get the previous value of an attribute, recorded at the time the last + // `"change"` event was fired. + previous: function(attr) { + if (attr == null || !this._previousAttributes) return null; + return this._previousAttributes[attr]; + }, + + // Get all of the attributes of the model at the time of the previous + // `"change"` event. + previousAttributes: function() { + return _.clone(this._previousAttributes); + }, + + // Fetch the model from the server, merging the response with the model's + // local attributes. Any changed attributes will trigger a "change" event. + fetch: function(options) { + options = _.extend({parse: true}, options); + var model = this; + var success = options.success; + options.success = function(resp) { + var serverAttrs = options.parse ? model.parse(resp, options) : resp; + if (!model.set(serverAttrs, options)) return false; + if (success) success.call(options.context, model, resp, options); + model.trigger('sync', model, resp, options); + }; + wrapError(this, options); + return this.sync('read', this, options); + }, + + // Set a hash of model attributes, and sync the model to the server. + // If the server returns an attributes hash that differs, the model's + // state will be `set` again. + save: function(key, val, options) { + // Handle both `"key", value` and `{key: value}` -style arguments. + var attrs; + if (key == null || typeof key === 'object') { + attrs = key; + options = val; + } else { + (attrs = {})[key] = val; + } + + options = _.extend({validate: true, parse: true}, options); + var wait = options.wait; + + // If we're not waiting and attributes exist, save acts as + // `set(attr).save(null, opts)` with validation. Otherwise, check if + // the model will be valid when the attributes, if any, are set. + if (attrs && !wait) { + if (!this.set(attrs, options)) return false; + } else if (!this._validate(attrs, options)) { + return false; + } + + // After a successful server-side save, the client is (optionally) + // updated with the server-side state. + var model = this; + var success = options.success; + var attributes = this.attributes; + options.success = function(resp) { + // Ensure attributes are restored during synchronous saves. + model.attributes = attributes; + var serverAttrs = options.parse ? model.parse(resp, options) : resp; + if (wait) serverAttrs = _.extend({}, attrs, serverAttrs); + if (serverAttrs && !model.set(serverAttrs, options)) return false; + if (success) success.call(options.context, model, resp, options); + model.trigger('sync', model, resp, options); + }; + wrapError(this, options); + + // Set temporary attributes if `{wait: true}` to properly find new ids. + if (attrs && wait) this.attributes = _.extend({}, attributes, attrs); + + var method = this.isNew() ? 'create' : options.patch ? 'patch' : 'update'; + if (method === 'patch' && !options.attrs) options.attrs = attrs; + var xhr = this.sync(method, this, options); + + // Restore attributes. + this.attributes = attributes; + + return xhr; + }, + + // Destroy this model on the server if it was already persisted. + // Optimistically removes the model from its collection, if it has one. + // If `wait: true` is passed, waits for the server to respond before removal. + destroy: function(options) { + options = options ? _.clone(options) : {}; + var model = this; + var success = options.success; + var wait = options.wait; + + var destroy = function() { + model.stopListening(); + model.trigger('destroy', model, model.collection, options); + }; + + options.success = function(resp) { + if (wait) destroy(); + if (success) success.call(options.context, model, resp, options); + if (!model.isNew()) model.trigger('sync', model, resp, options); + }; + + var xhr = false; + if (this.isNew()) { + _.defer(options.success); + } else { + wrapError(this, options); + xhr = this.sync('delete', this, options); + } + if (!wait) destroy(); + return xhr; + }, + + // Default URL for the model's representation on the server -- if you're + // using Backbone's restful methods, override this to change the endpoint + // that will be called. + url: function() { + var base = + _.result(this, 'urlRoot') || + _.result(this.collection, 'url') || + urlError(); + if (this.isNew()) return base; + var id = this.get(this.idAttribute); + return base.replace(/[^\/]$/, '$&/') + encodeURIComponent(id); + }, + + // **parse** converts a response into the hash of attributes to be `set` on + // the model. The default implementation is just to pass the response along. + parse: function(resp, options) { + return resp; + }, + + // Create a new model with identical attributes to this one. + clone: function() { + return new this.constructor(this.attributes); + }, + + // A model is new if it has never been saved to the server, and lacks an id. + isNew: function() { + return !this.has(this.idAttribute); + }, + + // Check if the model is currently in a valid state. + isValid: function(options) { + return this._validate({}, _.extend({}, options, {validate: true})); + }, + + // Run validation against the next complete set of model attributes, + // returning `true` if all is well. Otherwise, fire an `"invalid"` event. + _validate: function(attrs, options) { + if (!options.validate || !this.validate) return true; + attrs = _.extend({}, this.attributes, attrs); + var error = this.validationError = this.validate(attrs, options) || null; + if (!error) return true; + this.trigger('invalid', this, error, _.extend(options, {validationError: error})); + return false; + } + + }); + + // Backbone.Collection + // ------------------- + + // If models tend to represent a single row of data, a Backbone Collection is + // more analogous to a table full of data ... or a small slice or page of that + // table, or a collection of rows that belong together for a particular reason + // -- all of the messages in this particular folder, all of the documents + // belonging to this particular author, and so on. Collections maintain + // indexes of their models, both in order, and for lookup by `id`. + + // Create a new **Collection**, perhaps to contain a specific type of `model`. + // If a `comparator` is specified, the Collection will maintain + // its models in sort order, as they're added and removed. + var Collection = Backbone.Collection = function(models, options) { + options || (options = {}); + this.preinitialize.apply(this, arguments); + if (options.model) this.model = options.model; + if (options.comparator !== void 0) this.comparator = options.comparator; + this._reset(); + this.initialize.apply(this, arguments); + if (models) this.reset(models, _.extend({silent: true}, options)); + }; + + // Default options for `Collection#set`. + var setOptions = {add: true, remove: true, merge: true}; + var addOptions = {add: true, remove: false}; + + // Splices `insert` into `array` at index `at`. + var splice = function(array, insert, at) { + at = Math.min(Math.max(at, 0), array.length); + var tail = Array(array.length - at); + var length = insert.length; + var i; + for (i = 0; i < tail.length; i++) tail[i] = array[i + at]; + for (i = 0; i < length; i++) array[i + at] = insert[i]; + for (i = 0; i < tail.length; i++) array[i + length + at] = tail[i]; + }; + + // Define the Collection's inheritable methods. + _.extend(Collection.prototype, Events, { + + // The default model for a collection is just a **Backbone.Model**. + // This should be overridden in most cases. + model: Model, + + + // preinitialize is an empty function by default. You can override it with a function + // or object. preinitialize will run before any instantiation logic is run in the Collection. + preinitialize: function(){}, + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize: function(){}, + + // The JSON representation of a Collection is an array of the + // models' attributes. + toJSON: function(options) { + return this.map(function(model) { return model.toJSON(options); }); + }, + + // Proxy `Backbone.sync` by default. + sync: function() { + return Backbone.sync.apply(this, arguments); + }, + + // Add a model, or list of models to the set. `models` may be Backbone + // Models or raw JavaScript objects to be converted to Models, or any + // combination of the two. + add: function(models, options) { + return this.set(models, _.extend({merge: false}, options, addOptions)); + }, + + // Remove a model, or a list of models from the set. + remove: function(models, options) { + options = _.extend({}, options); + var singular = !_.isArray(models); + models = singular ? [models] : models.slice(); + var removed = this._removeModels(models, options); + if (!options.silent && removed.length) { + options.changes = {added: [], merged: [], removed: removed}; + this.trigger('update', this, options); + } + return singular ? removed[0] : removed; + }, + + // Update a collection by `set`-ing a new list of models, adding new ones, + // removing models that are no longer present, and merging models that + // already exist in the collection, as necessary. Similar to **Model#set**, + // the core operation for updating the data contained by the collection. + set: function(models, options) { + if (models == null) return; + + options = _.extend({}, setOptions, options); + if (options.parse && !this._isModel(models)) { + models = this.parse(models, options) || []; + } + + var singular = !_.isArray(models); + models = singular ? [models] : models.slice(); + + var at = options.at; + if (at != null) at = +at; + if (at > this.length) at = this.length; + if (at < 0) at += this.length + 1; + + var set = []; + var toAdd = []; + var toMerge = []; + var toRemove = []; + var modelMap = {}; + + var add = options.add; + var merge = options.merge; + var remove = options.remove; + + var sort = false; + var sortable = this.comparator && at == null && options.sort !== false; + var sortAttr = _.isString(this.comparator) ? this.comparator : null; + + // Turn bare objects into model references, and prevent invalid models + // from being added. + var model, i; + for (i = 0; i < models.length; i++) { + model = models[i]; + + // If a duplicate is found, prevent it from being added and + // optionally merge it into the existing model. + var existing = this.get(model); + if (existing) { + if (merge && model !== existing) { + var attrs = this._isModel(model) ? model.attributes : model; + if (options.parse) attrs = existing.parse(attrs, options); + existing.set(attrs, options); + toMerge.push(existing); + if (sortable && !sort) sort = existing.hasChanged(sortAttr); + } + if (!modelMap[existing.cid]) { + modelMap[existing.cid] = true; + set.push(existing); + } + models[i] = existing; + + // If this is a new, valid model, push it to the `toAdd` list. + } else if (add) { + model = models[i] = this._prepareModel(model, options); + if (model) { + toAdd.push(model); + this._addReference(model, options); + modelMap[model.cid] = true; + set.push(model); + } + } + } + + // Remove stale models. + if (remove) { + for (i = 0; i < this.length; i++) { + model = this.models[i]; + if (!modelMap[model.cid]) toRemove.push(model); + } + if (toRemove.length) this._removeModels(toRemove, options); + } + + // See if sorting is needed, update `length` and splice in new models. + var orderChanged = false; + var replace = !sortable && add && remove; + if (set.length && replace) { + orderChanged = this.length !== set.length || _.some(this.models, function(m, index) { + return m !== set[index]; + }); + this.models.length = 0; + splice(this.models, set, 0); + this.length = this.models.length; + } else if (toAdd.length) { + if (sortable) sort = true; + splice(this.models, toAdd, at == null ? this.length : at); + this.length = this.models.length; + } + + // Silently sort the collection if appropriate. + if (sort) this.sort({silent: true}); + + // Unless silenced, it's time to fire all appropriate add/sort/update events. + if (!options.silent) { + for (i = 0; i < toAdd.length; i++) { + if (at != null) options.index = at + i; + model = toAdd[i]; + model.trigger('add', model, this, options); + } + if (sort || orderChanged) this.trigger('sort', this, options); + if (toAdd.length || toRemove.length || toMerge.length) { + options.changes = { + added: toAdd, + removed: toRemove, + merged: toMerge + }; + this.trigger('update', this, options); + } + } + + // Return the added (or merged) model (or models). + return singular ? models[0] : models; + }, + + // When you have more items than you want to add or remove individually, + // you can reset the entire set with a new list of models, without firing + // any granular `add` or `remove` events. Fires `reset` when finished. + // Useful for bulk operations and optimizations. + reset: function(models, options) { + options = options ? _.clone(options) : {}; + for (var i = 0; i < this.models.length; i++) { + this._removeReference(this.models[i], options); + } + options.previousModels = this.models; + this._reset(); + models = this.add(models, _.extend({silent: true}, options)); + if (!options.silent) this.trigger('reset', this, options); + return models; + }, + + // Add a model to the end of the collection. + push: function(model, options) { + return this.add(model, _.extend({at: this.length}, options)); + }, + + // Remove a model from the end of the collection. + pop: function(options) { + var model = this.at(this.length - 1); + return this.remove(model, options); + }, + + // Add a model to the beginning of the collection. + unshift: function(model, options) { + return this.add(model, _.extend({at: 0}, options)); + }, + + // Remove a model from the beginning of the collection. + shift: function(options) { + var model = this.at(0); + return this.remove(model, options); + }, + + // Slice out a sub-array of models from the collection. + slice: function() { + return slice.apply(this.models, arguments); + }, + + // Get a model from the set by id, cid, model object with id or cid + // properties, or an attributes object that is transformed through modelId. + get: function(obj) { + if (obj == null) return void 0; + return this._byId[obj] || + this._byId[this.modelId(this._isModel(obj) ? obj.attributes : obj)] || + obj.cid && this._byId[obj.cid]; + }, + + // Returns `true` if the model is in the collection. + has: function(obj) { + return this.get(obj) != null; + }, + + // Get the model at the given index. + at: function(index) { + if (index < 0) index += this.length; + return this.models[index]; + }, + + // Return models with matching attributes. Useful for simple cases of + // `filter`. + where: function(attrs, first) { + return this[first ? 'find' : 'filter'](attrs); + }, + + // Return the first model with matching attributes. Useful for simple cases + // of `find`. + findWhere: function(attrs) { + return this.where(attrs, true); + }, + + // Force the collection to re-sort itself. You don't need to call this under + // normal circumstances, as the set will maintain sort order as each item + // is added. + sort: function(options) { + var comparator = this.comparator; + if (!comparator) throw new Error('Cannot sort a set without a comparator'); + options || (options = {}); + + var length = comparator.length; + if (_.isFunction(comparator)) comparator = comparator.bind(this); + + // Run sort based on type of `comparator`. + if (length === 1 || _.isString(comparator)) { + this.models = this.sortBy(comparator); + } else { + this.models.sort(comparator); + } + if (!options.silent) this.trigger('sort', this, options); + return this; + }, + + // Pluck an attribute from each model in the collection. + pluck: function(attr) { + return this.map(attr + ''); + }, + + // Fetch the default set of models for this collection, resetting the + // collection when they arrive. If `reset: true` is passed, the response + // data will be passed through the `reset` method instead of `set`. + fetch: function(options) { + options = _.extend({parse: true}, options); + var success = options.success; + var collection = this; + options.success = function(resp) { + var method = options.reset ? 'reset' : 'set'; + collection[method](resp, options); + if (success) success.call(options.context, collection, resp, options); + collection.trigger('sync', collection, resp, options); + }; + wrapError(this, options); + return this.sync('read', this, options); + }, + + // Create a new instance of a model in this collection. Add the model to the + // collection immediately, unless `wait: true` is passed, in which case we + // wait for the server to agree. + create: function(model, options) { + options = options ? _.clone(options) : {}; + var wait = options.wait; + model = this._prepareModel(model, options); + if (!model) return false; + if (!wait) this.add(model, options); + var collection = this; + var success = options.success; + options.success = function(m, resp, callbackOpts) { + if (wait) collection.add(m, callbackOpts); + if (success) success.call(callbackOpts.context, m, resp, callbackOpts); + }; + model.save(null, options); + return model; + }, + + // **parse** converts a response into a list of models to be added to the + // collection. The default implementation is just to pass it through. + parse: function(resp, options) { + return resp; + }, + + // Create a new collection with an identical list of models as this one. + clone: function() { + return new this.constructor(this.models, { + model: this.model, + comparator: this.comparator + }); + }, + + // Define how to uniquely identify models in the collection. + modelId: function(attrs) { + return attrs[this.model.prototype.idAttribute || 'id']; + }, + + // Get an iterator of all models in this collection. + values: function() { + return new CollectionIterator(this, ITERATOR_VALUES); + }, + + // Get an iterator of all model IDs in this collection. + keys: function() { + return new CollectionIterator(this, ITERATOR_KEYS); + }, + + // Get an iterator of all [ID, model] tuples in this collection. + entries: function() { + return new CollectionIterator(this, ITERATOR_KEYSVALUES); + }, + + // Private method to reset all internal state. Called when the collection + // is first initialized or reset. + _reset: function() { + this.length = 0; + this.models = []; + this._byId = {}; + }, + + // Prepare a hash of attributes (or other model) to be added to this + // collection. + _prepareModel: function(attrs, options) { + if (this._isModel(attrs)) { + if (!attrs.collection) attrs.collection = this; + return attrs; + } + options = options ? _.clone(options) : {}; + options.collection = this; + var model = new this.model(attrs, options); + if (!model.validationError) return model; + this.trigger('invalid', this, model.validationError, options); + return false; + }, + + // Internal method called by both remove and set. + _removeModels: function(models, options) { + var removed = []; + for (var i = 0; i < models.length; i++) { + var model = this.get(models[i]); + if (!model) continue; + + var index = this.indexOf(model); + this.models.splice(index, 1); + this.length--; + + // Remove references before triggering 'remove' event to prevent an + // infinite loop. #3693 + delete this._byId[model.cid]; + var id = this.modelId(model.attributes); + if (id != null) delete this._byId[id]; + + if (!options.silent) { + options.index = index; + model.trigger('remove', model, this, options); + } + + removed.push(model); + this._removeReference(model, options); + } + return removed; + }, + + // Method for checking whether an object should be considered a model for + // the purposes of adding to the collection. + _isModel: function(model) { + return model instanceof Model; + }, + + // Internal method to create a model's ties to a collection. + _addReference: function(model, options) { + this._byId[model.cid] = model; + var id = this.modelId(model.attributes); + if (id != null) this._byId[id] = model; + model.on('all', this._onModelEvent, this); + }, + + // Internal method to sever a model's ties to a collection. + _removeReference: function(model, options) { + delete this._byId[model.cid]; + var id = this.modelId(model.attributes); + if (id != null) delete this._byId[id]; + if (this === model.collection) delete model.collection; + model.off('all', this._onModelEvent, this); + }, + + // Internal method called every time a model in the set fires an event. + // Sets need to update their indexes when models change ids. All other + // events simply proxy through. "add" and "remove" events that originate + // in other collections are ignored. + _onModelEvent: function(event, model, collection, options) { + if (model) { + if ((event === 'add' || event === 'remove') && collection !== this) return; + if (event === 'destroy') this.remove(model, options); + if (event === 'change') { + var prevId = this.modelId(model.previousAttributes()); + var id = this.modelId(model.attributes); + if (prevId !== id) { + if (prevId != null) delete this._byId[prevId]; + if (id != null) this._byId[id] = model; + } + } + } + this.trigger.apply(this, arguments); + } + + }); + + // Defining an @@iterator method implements JavaScript's Iterable protocol. + // In modern ES2015 browsers, this value is found at Symbol.iterator. + /* global Symbol */ + var $$iterator = typeof Symbol === 'function' && Symbol.iterator; + if ($$iterator) { + Collection.prototype[$$iterator] = Collection.prototype.values; + } + + // CollectionIterator + // ------------------ + + // A CollectionIterator implements JavaScript's Iterator protocol, allowing the + // use of `for of` loops in modern browsers and interoperation between + // Backbone.Collection and other JavaScript functions and third-party libraries + // which can operate on Iterables. + var CollectionIterator = function(collection, kind) { + this._collection = collection; + this._kind = kind; + this._index = 0; + }; + + // This "enum" defines the three possible kinds of values which can be emitted + // by a CollectionIterator that correspond to the values(), keys() and entries() + // methods on Collection, respectively. + var ITERATOR_VALUES = 1; + var ITERATOR_KEYS = 2; + var ITERATOR_KEYSVALUES = 3; + + // All Iterators should themselves be Iterable. + if ($$iterator) { + CollectionIterator.prototype[$$iterator] = function() { + return this; + }; + } + + CollectionIterator.prototype.next = function() { + if (this._collection) { + + // Only continue iterating if the iterated collection is long enough. + if (this._index < this._collection.length) { + var model = this._collection.at(this._index); + this._index++; + + // Construct a value depending on what kind of values should be iterated. + var value; + if (this._kind === ITERATOR_VALUES) { + value = model; + } else { + var id = this._collection.modelId(model.attributes); + if (this._kind === ITERATOR_KEYS) { + value = id; + } else { // ITERATOR_KEYSVALUES + value = [id, model]; + } + } + return {value: value, done: false}; + } + + // Once exhausted, remove the reference to the collection so future + // calls to the next method always return done. + this._collection = void 0; + } + + return {value: void 0, done: true}; + }; + + // Backbone.View + // ------------- + + // Backbone Views are almost more convention than they are actual code. A View + // is simply a JavaScript object that represents a logical chunk of UI in the + // DOM. This might be a single item, an entire list, a sidebar or panel, or + // even the surrounding frame which wraps your whole app. Defining a chunk of + // UI as a **View** allows you to define your DOM events declaratively, without + // having to worry about render order ... and makes it easy for the view to + // react to specific changes in the state of your models. + + // Creating a Backbone.View creates its initial element outside of the DOM, + // if an existing element is not provided... + var View = Backbone.View = function(options) { + this.cid = _.uniqueId('view'); + this.preinitialize.apply(this, arguments); + _.extend(this, _.pick(options, viewOptions)); + this._ensureElement(); + this.initialize.apply(this, arguments); + }; + + // Cached regex to split keys for `delegate`. + var delegateEventSplitter = /^(\S+)\s*(.*)$/; + + // List of view options to be set as properties. + var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events']; + + // Set up all inheritable **Backbone.View** properties and methods. + _.extend(View.prototype, Events, { + + // The default `tagName` of a View's element is `"div"`. + tagName: 'div', + + // jQuery delegate for element lookup, scoped to DOM elements within the + // current view. This should be preferred to global lookups where possible. + $: function(selector) { + return this.$el.find(selector); + }, + + // preinitialize is an empty function by default. You can override it with a function + // or object. preinitialize will run before any instantiation logic is run in the View + preinitialize: function(){}, + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize: function(){}, + + // **render** is the core function that your view should override, in order + // to populate its element (`this.el`), with the appropriate HTML. The + // convention is for **render** to always return `this`. + render: function() { + return this; + }, + + // Remove this view by taking the element out of the DOM, and removing any + // applicable Backbone.Events listeners. + remove: function() { + this._removeElement(); + this.stopListening(); + return this; + }, + + // Remove this view's element from the document and all event listeners + // attached to it. Exposed for subclasses using an alternative DOM + // manipulation API. + _removeElement: function() { + this.$el.remove(); + }, + + // Change the view's element (`this.el` property) and re-delegate the + // view's events on the new element. + setElement: function(element) { + this.undelegateEvents(); + this._setElement(element); + this.delegateEvents(); + return this; + }, + + // Creates the `this.el` and `this.$el` references for this view using the + // given `el`. `el` can be a CSS selector or an HTML string, a jQuery + // context or an element. Subclasses can override this to utilize an + // alternative DOM manipulation API and are only required to set the + // `this.el` property. + _setElement: function(el) { + this.$el = el instanceof Backbone.$ ? el : Backbone.$(el); + this.el = this.$el[0]; + }, + + // Set callbacks, where `this.events` is a hash of + // + // *{"event selector": "callback"}* + // + // { + // 'mousedown .title': 'edit', + // 'click .button': 'save', + // 'click .open': function(e) { ... } + // } + // + // pairs. Callbacks will be bound to the view, with `this` set properly. + // Uses event delegation for efficiency. + // Omitting the selector binds the event to `this.el`. + delegateEvents: function(events) { + events || (events = _.result(this, 'events')); + if (!events) return this; + this.undelegateEvents(); + for (var key in events) { + var method = events[key]; + if (!_.isFunction(method)) method = this[method]; + if (!method) continue; + var match = key.match(delegateEventSplitter); + this.delegate(match[1], match[2], method.bind(this)); + } + return this; + }, + + // Add a single event listener to the view's element (or a child element + // using `selector`). This only works for delegate-able events: not `focus`, + // `blur`, and not `change`, `submit`, and `reset` in Internet Explorer. + delegate: function(eventName, selector, listener) { + this.$el.on(eventName + '.delegateEvents' + this.cid, selector, listener); + return this; + }, + + // Clears all callbacks previously bound to the view by `delegateEvents`. + // You usually don't need to use this, but may wish to if you have multiple + // Backbone views attached to the same DOM element. + undelegateEvents: function() { + if (this.$el) this.$el.off('.delegateEvents' + this.cid); + return this; + }, + + // A finer-grained `undelegateEvents` for removing a single delegated event. + // `selector` and `listener` are both optional. + undelegate: function(eventName, selector, listener) { + this.$el.off(eventName + '.delegateEvents' + this.cid, selector, listener); + return this; + }, + + // Produces a DOM element to be assigned to your view. Exposed for + // subclasses using an alternative DOM manipulation API. + _createElement: function(tagName) { + return document.createElement(tagName); + }, + + // Ensure that the View has a DOM element to render into. + // If `this.el` is a string, pass it through `$()`, take the first + // matching element, and re-assign it to `el`. Otherwise, create + // an element from the `id`, `className` and `tagName` properties. + _ensureElement: function() { + if (!this.el) { + var attrs = _.extend({}, _.result(this, 'attributes')); + if (this.id) attrs.id = _.result(this, 'id'); + if (this.className) attrs['class'] = _.result(this, 'className'); + this.setElement(this._createElement(_.result(this, 'tagName'))); + this._setAttributes(attrs); + } else { + this.setElement(_.result(this, 'el')); + } + }, + + // Set attributes from a hash on this view's element. Exposed for + // subclasses using an alternative DOM manipulation API. + _setAttributes: function(attributes) { + this.$el.attr(attributes); + } + + }); + + // Proxy Backbone class methods to Underscore functions, wrapping the model's + // `attributes` object or collection's `models` array behind the scenes. + // + // collection.filter(function(model) { return model.get('age') > 10 }); + // collection.each(this.addView); + // + // `Function#apply` can be slow so we use the method's arg count, if we know it. + var addMethod = function(base, length, method, attribute) { + switch (length) { + case 1: return function() { + return base[method](this[attribute]); + }; + case 2: return function(value) { + return base[method](this[attribute], value); + }; + case 3: return function(iteratee, context) { + return base[method](this[attribute], cb(iteratee, this), context); + }; + case 4: return function(iteratee, defaultVal, context) { + return base[method](this[attribute], cb(iteratee, this), defaultVal, context); + }; + default: return function() { + var args = slice.call(arguments); + args.unshift(this[attribute]); + return base[method].apply(base, args); + }; + } + }; + + var addUnderscoreMethods = function(Class, base, methods, attribute) { + _.each(methods, function(length, method) { + if (base[method]) Class.prototype[method] = addMethod(base, length, method, attribute); + }); + }; + + // Support `collection.sortBy('attr')` and `collection.findWhere({id: 1})`. + var cb = function(iteratee, instance) { + if (_.isFunction(iteratee)) return iteratee; + if (_.isObject(iteratee) && !instance._isModel(iteratee)) return modelMatcher(iteratee); + if (_.isString(iteratee)) return function(model) { return model.get(iteratee); }; + return iteratee; + }; + var modelMatcher = function(attrs) { + var matcher = _.matches(attrs); + return function(model) { + return matcher(model.attributes); + }; + }; + + // Underscore methods that we want to implement on the Collection. + // 90% of the core usefulness of Backbone Collections is actually implemented + // right here: + var collectionMethods = {forEach: 3, each: 3, map: 3, collect: 3, reduce: 0, + foldl: 0, inject: 0, reduceRight: 0, foldr: 0, find: 3, detect: 3, filter: 3, + select: 3, reject: 3, every: 3, all: 3, some: 3, any: 3, include: 3, includes: 3, + contains: 3, invoke: 0, max: 3, min: 3, toArray: 1, size: 1, first: 3, + head: 3, take: 3, initial: 3, rest: 3, tail: 3, drop: 3, last: 3, + without: 0, difference: 0, indexOf: 3, shuffle: 1, lastIndexOf: 3, + isEmpty: 1, chain: 1, sample: 3, partition: 3, groupBy: 3, countBy: 3, + sortBy: 3, indexBy: 3, findIndex: 3, findLastIndex: 3}; + + + // Underscore methods that we want to implement on the Model, mapped to the + // number of arguments they take. + var modelMethods = {keys: 1, values: 1, pairs: 1, invert: 1, pick: 0, + omit: 0, chain: 1, isEmpty: 1}; + + // Mix in each Underscore method as a proxy to `Collection#models`. + + _.each([ + [Collection, collectionMethods, 'models'], + [Model, modelMethods, 'attributes'] + ], function(config) { + var Base = config[0], + methods = config[1], + attribute = config[2]; + + Base.mixin = function(obj) { + var mappings = _.reduce(_.functions(obj), function(memo, name) { + memo[name] = 0; + return memo; + }, {}); + addUnderscoreMethods(Base, obj, mappings, attribute); + }; + + addUnderscoreMethods(Base, _, methods, attribute); + }); + + // Backbone.sync + // ------------- + + // Override this function to change the manner in which Backbone persists + // models to the server. You will be passed the type of request, and the + // model in question. By default, makes a RESTful Ajax request + // to the model's `url()`. Some possible customizations could be: + // + // * Use `setTimeout` to batch rapid-fire updates into a single request. + // * Send up the models as XML instead of JSON. + // * Persist models via WebSockets instead of Ajax. + // + // Turn on `Backbone.emulateHTTP` in order to send `PUT` and `DELETE` requests + // as `POST`, with a `_method` parameter containing the true HTTP method, + // as well as all requests with the body as `application/x-www-form-urlencoded` + // instead of `application/json` with the model in a param named `model`. + // Useful when interfacing with server-side languages like **PHP** that make + // it difficult to read the body of `PUT` requests. + Backbone.sync = function(method, model, options) { + var type = methodMap[method]; + + // Default options, unless specified. + _.defaults(options || (options = {}), { + emulateHTTP: Backbone.emulateHTTP, + emulateJSON: Backbone.emulateJSON + }); + + // Default JSON-request options. + var params = {type: type, dataType: 'json'}; + + // Ensure that we have a URL. + if (!options.url) { + params.url = _.result(model, 'url') || urlError(); + } + + // Ensure that we have the appropriate request data. + if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) { + params.contentType = 'application/json'; + params.data = JSON.stringify(options.attrs || model.toJSON(options)); + } + + // For older servers, emulate JSON by encoding the request into an HTML-form. + if (options.emulateJSON) { + params.contentType = 'application/x-www-form-urlencoded'; + params.data = params.data ? {model: params.data} : {}; + } + + // For older servers, emulate HTTP by mimicking the HTTP method with `_method` + // And an `X-HTTP-Method-Override` header. + if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) { + params.type = 'POST'; + if (options.emulateJSON) params.data._method = type; + var beforeSend = options.beforeSend; + options.beforeSend = function(xhr) { + xhr.setRequestHeader('X-HTTP-Method-Override', type); + if (beforeSend) return beforeSend.apply(this, arguments); + }; + } + + // Don't process data on a non-GET request. + if (params.type !== 'GET' && !options.emulateJSON) { + params.processData = false; + } + + // Pass along `textStatus` and `errorThrown` from jQuery. + var error = options.error; + options.error = function(xhr, textStatus, errorThrown) { + options.textStatus = textStatus; + options.errorThrown = errorThrown; + if (error) error.call(options.context, xhr, textStatus, errorThrown); + }; + + // Make the request, allowing the user to override any Ajax options. + var xhr = options.xhr = Backbone.ajax(_.extend(params, options)); + model.trigger('request', model, xhr, options); + return xhr; + }; + + // Map from CRUD to HTTP for our default `Backbone.sync` implementation. + var methodMap = { + create: 'POST', + update: 'PUT', + patch: 'PATCH', + delete: 'DELETE', + read: 'GET' + }; + + // Set the default implementation of `Backbone.ajax` to proxy through to `$`. + // Override this if you'd like to use a different library. + Backbone.ajax = function() { + return Backbone.$.ajax.apply(Backbone.$, arguments); + }; + + // Backbone.Router + // --------------- + + // Routers map faux-URLs to actions, and fire events when routes are + // matched. Creating a new one sets its `routes` hash, if not set statically. + var Router = Backbone.Router = function(options) { + options || (options = {}); + this.preinitialize.apply(this, arguments); + if (options.routes) this.routes = options.routes; + this._bindRoutes(); + this.initialize.apply(this, arguments); + }; + + // Cached regular expressions for matching named param parts and splatted + // parts of route strings. + var optionalParam = /\((.*?)\)/g; + var namedParam = /(\(\?)?:\w+/g; + var splatParam = /\*\w+/g; + var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g; + + // Set up all inheritable **Backbone.Router** properties and methods. + _.extend(Router.prototype, Events, { + + // preinitialize is an empty function by default. You can override it with a function + // or object. preinitialize will run before any instantiation logic is run in the Router. + preinitialize: function(){}, + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize: function(){}, + + // Manually bind a single named route to a callback. For example: + // + // this.route('search/:query/p:num', 'search', function(query, num) { + // ... + // }); + // + route: function(route, name, callback) { + if (!_.isRegExp(route)) route = this._routeToRegExp(route); + if (_.isFunction(name)) { + callback = name; + name = ''; + } + if (!callback) callback = this[name]; + var router = this; + Backbone.history.route(route, function(fragment) { + var args = router._extractParameters(route, fragment); + if (router.execute(callback, args, name) !== false) { + router.trigger.apply(router, ['route:' + name].concat(args)); + router.trigger('route', name, args); + Backbone.history.trigger('route', router, name, args); + } + }); + return this; + }, + + // Execute a route handler with the provided parameters. This is an + // excellent place to do pre-route setup or post-route cleanup. + execute: function(callback, args, name) { + if (callback) callback.apply(this, args); + }, + + // Simple proxy to `Backbone.history` to save a fragment into the history. + navigate: function(fragment, options) { + Backbone.history.navigate(fragment, options); + return this; + }, + + // Bind all defined routes to `Backbone.history`. We have to reverse the + // order of the routes here to support behavior where the most general + // routes can be defined at the bottom of the route map. + _bindRoutes: function() { + if (!this.routes) return; + this.routes = _.result(this, 'routes'); + var route, routes = _.keys(this.routes); + while ((route = routes.pop()) != null) { + this.route(route, this.routes[route]); + } + }, + + // Convert a route string into a regular expression, suitable for matching + // against the current location hash. + _routeToRegExp: function(route) { + route = route.replace(escapeRegExp, '\\$&') + .replace(optionalParam, '(?:$1)?') + .replace(namedParam, function(match, optional) { + return optional ? match : '([^/?]+)'; + }) + .replace(splatParam, '([^?]*?)'); + return new RegExp('^' + route + '(?:\\?([\\s\\S]*))?$'); + }, + + // Given a route, and a URL fragment that it matches, return the array of + // extracted decoded parameters. Empty or unmatched parameters will be + // treated as `null` to normalize cross-browser behavior. + _extractParameters: function(route, fragment) { + var params = route.exec(fragment).slice(1); + return _.map(params, function(param, i) { + // Don't decode the search params. + if (i === params.length - 1) return param || null; + return param ? decodeURIComponent(param) : null; + }); + } + + }); + + // Backbone.History + // ---------------- + + // Handles cross-browser history management, based on either + // [pushState](http://diveintohtml5.info/history.html) and real URLs, or + // [onhashchange](https://developer.mozilla.org/en-US/docs/DOM/window.onhashchange) + // and URL fragments. If the browser supports neither (old IE, natch), + // falls back to polling. + var History = Backbone.History = function() { + this.handlers = []; + this.checkUrl = this.checkUrl.bind(this); + + // Ensure that `History` can be used outside of the browser. + if (typeof window !== 'undefined') { + this.location = window.location; + this.history = window.history; + } + }; + + // Cached regex for stripping a leading hash/slash and trailing space. + var routeStripper = /^[#\/]|\s+$/g; + + // Cached regex for stripping leading and trailing slashes. + var rootStripper = /^\/+|\/+$/g; + + // Cached regex for stripping urls of hash. + var pathStripper = /#.*$/; + + // Has the history handling already been started? + History.started = false; + + // Set up all inheritable **Backbone.History** properties and methods. + _.extend(History.prototype, Events, { + + // The default interval to poll for hash changes, if necessary, is + // twenty times a second. + interval: 50, + + // Are we at the app root? + atRoot: function() { + var path = this.location.pathname.replace(/[^\/]$/, '$&/'); + return path === this.root && !this.getSearch(); + }, + + // Does the pathname match the root? + matchRoot: function() { + var path = this.decodeFragment(this.location.pathname); + var rootPath = path.slice(0, this.root.length - 1) + '/'; + return rootPath === this.root; + }, + + // Unicode characters in `location.pathname` are percent encoded so they're + // decoded for comparison. `%25` should not be decoded since it may be part + // of an encoded parameter. + decodeFragment: function(fragment) { + return decodeURI(fragment.replace(/%25/g, '%2525')); + }, + + // In IE6, the hash fragment and search params are incorrect if the + // fragment contains `?`. + getSearch: function() { + var match = this.location.href.replace(/#.*/, '').match(/\?.+/); + return match ? match[0] : ''; + }, + + // Gets the true hash value. Cannot use location.hash directly due to bug + // in Firefox where location.hash will always be decoded. + getHash: function(window) { + var match = (window || this).location.href.match(/#(.*)$/); + return match ? match[1] : ''; + }, + + // Get the pathname and search params, without the root. + getPath: function() { + var path = this.decodeFragment( + this.location.pathname + this.getSearch() + ).slice(this.root.length - 1); + return path.charAt(0) === '/' ? path.slice(1) : path; + }, + + // Get the cross-browser normalized URL fragment from the path or hash. + getFragment: function(fragment) { + if (fragment == null) { + if (this._usePushState || !this._wantsHashChange) { + fragment = this.getPath(); + } else { + fragment = this.getHash(); + } + } + return fragment.replace(routeStripper, ''); + }, + + // Start the hash change handling, returning `true` if the current URL matches + // an existing route, and `false` otherwise. + start: function(options) { + if (History.started) throw new Error('Backbone.history has already been started'); + History.started = true; + + // Figure out the initial configuration. Do we need an iframe? + // Is pushState desired ... is it available? + this.options = _.extend({root: '/'}, this.options, options); + this.root = this.options.root; + this._wantsHashChange = this.options.hashChange !== false; + this._hasHashChange = 'onhashchange' in window && (document.documentMode === void 0 || document.documentMode > 7); + this._useHashChange = this._wantsHashChange && this._hasHashChange; + this._wantsPushState = !!this.options.pushState; + this._hasPushState = !!(this.history && this.history.pushState); + this._usePushState = this._wantsPushState && this._hasPushState; + this.fragment = this.getFragment(); + + // Normalize root to always include a leading and trailing slash. + this.root = ('/' + this.root + '/').replace(rootStripper, '/'); + + // Transition from hashChange to pushState or vice versa if both are + // requested. + if (this._wantsHashChange && this._wantsPushState) { + + // If we've started off with a route from a `pushState`-enabled + // browser, but we're currently in a browser that doesn't support it... + if (!this._hasPushState && !this.atRoot()) { + var rootPath = this.root.slice(0, -1) || '/'; + this.location.replace(rootPath + '#' + this.getPath()); + // Return immediately as browser will do redirect to new url + return true; + + // Or if we've started out with a hash-based route, but we're currently + // in a browser where it could be `pushState`-based instead... + } else if (this._hasPushState && this.atRoot()) { + this.navigate(this.getHash(), {replace: true}); + } + + } + + // Proxy an iframe to handle location events if the browser doesn't + // support the `hashchange` event, HTML5 history, or the user wants + // `hashChange` but not `pushState`. + if (!this._hasHashChange && this._wantsHashChange && !this._usePushState) { + this.iframe = document.createElement('iframe'); + this.iframe.src = 'javascript:0'; + this.iframe.style.display = 'none'; + this.iframe.tabIndex = -1; + var body = document.body; + // Using `appendChild` will throw on IE < 9 if the document is not ready. + var iWindow = body.insertBefore(this.iframe, body.firstChild).contentWindow; + iWindow.document.open(); + iWindow.document.close(); + iWindow.location.hash = '#' + this.fragment; + } + + // Add a cross-platform `addEventListener` shim for older browsers. + var addEventListener = window.addEventListener || function(eventName, listener) { + return attachEvent('on' + eventName, listener); + }; + + // Depending on whether we're using pushState or hashes, and whether + // 'onhashchange' is supported, determine how we check the URL state. + if (this._usePushState) { + addEventListener('popstate', this.checkUrl, false); + } else if (this._useHashChange && !this.iframe) { + addEventListener('hashchange', this.checkUrl, false); + } else if (this._wantsHashChange) { + this._checkUrlInterval = setInterval(this.checkUrl, this.interval); + } + + if (!this.options.silent) return this.loadUrl(); + }, + + // Disable Backbone.history, perhaps temporarily. Not useful in a real app, + // but possibly useful for unit testing Routers. + stop: function() { + // Add a cross-platform `removeEventListener` shim for older browsers. + var removeEventListener = window.removeEventListener || function(eventName, listener) { + return detachEvent('on' + eventName, listener); + }; + + // Remove window listeners. + if (this._usePushState) { + removeEventListener('popstate', this.checkUrl, false); + } else if (this._useHashChange && !this.iframe) { + removeEventListener('hashchange', this.checkUrl, false); + } + + // Clean up the iframe if necessary. + if (this.iframe) { + document.body.removeChild(this.iframe); + this.iframe = null; + } + + // Some environments will throw when clearing an undefined interval. + if (this._checkUrlInterval) clearInterval(this._checkUrlInterval); + History.started = false; + }, + + // Add a route to be tested when the fragment changes. Routes added later + // may override previous routes. + route: function(route, callback) { + this.handlers.unshift({route: route, callback: callback}); + }, + + // Checks the current URL to see if it has changed, and if it has, + // calls `loadUrl`, normalizing across the hidden iframe. + checkUrl: function(e) { + var current = this.getFragment(); + + // If the user pressed the back button, the iframe's hash will have + // changed and we should use that for comparison. + if (current === this.fragment && this.iframe) { + current = this.getHash(this.iframe.contentWindow); + } + + if (current === this.fragment) return false; + if (this.iframe) this.navigate(current); + this.loadUrl(); + }, + + // Attempt to load the current URL fragment. If a route succeeds with a + // match, returns `true`. If no defined routes matches the fragment, + // returns `false`. + loadUrl: function(fragment) { + // If the root doesn't match, no routes can match either. + if (!this.matchRoot()) return false; + fragment = this.fragment = this.getFragment(fragment); + return _.some(this.handlers, function(handler) { + if (handler.route.test(fragment)) { + handler.callback(fragment); + return true; + } + }); + }, + + // Save a fragment into the hash history, or replace the URL state if the + // 'replace' option is passed. You are responsible for properly URL-encoding + // the fragment in advance. + // + // The options object can contain `trigger: true` if you wish to have the + // route callback be fired (not usually desirable), or `replace: true`, if + // you wish to modify the current URL without adding an entry to the history. + navigate: function(fragment, options) { + if (!History.started) return false; + if (!options || options === true) options = {trigger: !!options}; + + // Normalize the fragment. + fragment = this.getFragment(fragment || ''); + + // Don't include a trailing slash on the root. + var rootPath = this.root; + if (fragment === '' || fragment.charAt(0) === '?') { + rootPath = rootPath.slice(0, -1) || '/'; + } + var url = rootPath + fragment; + + // Strip the fragment of the query and hash for matching. + fragment = fragment.replace(pathStripper, ''); + + // Decode for matching. + var decodedFragment = this.decodeFragment(fragment); + + if (this.fragment === decodedFragment) return; + this.fragment = decodedFragment; + + // If pushState is available, we use it to set the fragment as a real URL. + if (this._usePushState) { + this.history[options.replace ? 'replaceState' : 'pushState']({}, document.title, url); + + // If hash changes haven't been explicitly disabled, update the hash + // fragment to store history. + } else if (this._wantsHashChange) { + this._updateHash(this.location, fragment, options.replace); + if (this.iframe && fragment !== this.getHash(this.iframe.contentWindow)) { + var iWindow = this.iframe.contentWindow; + + // Opening and closing the iframe tricks IE7 and earlier to push a + // history entry on hash-tag change. When replace is true, we don't + // want this. + if (!options.replace) { + iWindow.document.open(); + iWindow.document.close(); + } + + this._updateHash(iWindow.location, fragment, options.replace); + } + + // If you've told us that you explicitly don't want fallback hashchange- + // based history, then `navigate` becomes a page refresh. + } else { + return this.location.assign(url); + } + if (options.trigger) return this.loadUrl(fragment); + }, + + // Update the hash location, either replacing the current entry, or adding + // a new one to the browser history. + _updateHash: function(location, fragment, replace) { + if (replace) { + var href = location.href.replace(/(javascript:|#).*$/, ''); + location.replace(href + '#' + fragment); + } else { + // Some browsers require that `hash` contains a leading #. + location.hash = '#' + fragment; + } + } + + }); + + // Create the default Backbone.history. + Backbone.history = new History; + + // Helpers + // ------- + + // Helper function to correctly set up the prototype chain for subclasses. + // Similar to `goog.inherits`, but uses a hash of prototype properties and + // class properties to be extended. + var extend = function(protoProps, staticProps) { + var parent = this; + var child; + + // The constructor function for the new subclass is either defined by you + // (the "constructor" property in your `extend` definition), or defaulted + // by us to simply call the parent constructor. + if (protoProps && _.has(protoProps, 'constructor')) { + child = protoProps.constructor; + } else { + child = function(){ return parent.apply(this, arguments); }; + } + + // Add static properties to the constructor function, if supplied. + _.extend(child, parent, staticProps); + + // Set the prototype chain to inherit from `parent`, without calling + // `parent`'s constructor function and add the prototype properties. + child.prototype = _.create(parent.prototype, protoProps); + child.prototype.constructor = child; + + // Set a convenience property in case the parent's prototype is needed + // later. + child.__super__ = parent.prototype; + + return child; + }; + + // Set up inheritance for the model, collection, router, view and history. + Model.extend = Collection.extend = Router.extend = View.extend = History.extend = extend; + + // Throw an error when a URL is needed, and none is supplied. + var urlError = function() { + throw new Error('A "url" property or function must be specified'); + }; + + // Wrap an optional error callback with a fallback error event. + var wrapError = function(model, options) { + var error = options.error; + options.error = function(resp) { + if (error) error.call(options.context, model, resp, options); + model.trigger('error', model, resp, options); + }; + }; + + return Backbone; +}); diff --git a/openid-connect-server-webapp/src/main/webapp/resources/js/lib/jquery.js b/openid-connect-server-webapp/src/main/webapp/resources/js/lib/jquery.js index 6feb11086f..b9f8937fdd 100644 --- a/openid-connect-server-webapp/src/main/webapp/resources/js/lib/jquery.js +++ b/openid-connect-server-webapp/src/main/webapp/resources/js/lib/jquery.js @@ -1,27 +1,29 @@ /*! - * jQuery JavaScript Library v1.11.3 - * http://jquery.com/ + * jQuery JavaScript Library v3.6.0 + * https://jquery.com/ * * Includes Sizzle.js - * http://sizzlejs.com/ + * https://sizzlejs.com/ * - * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors + * Copyright OpenJS Foundation and other contributors * Released under the MIT license - * http://jquery.org/license + * https://jquery.org/license * - * Date: 2015-04-28T16:19Z + * Date: 2021-03-02T17:08Z */ +( function( global, factory ) { -(function( global, factory ) { + "use strict"; if ( typeof module === "object" && typeof module.exports === "object" ) { - // For CommonJS and CommonJS-like environments where a proper window is present, - // execute the factory and get jQuery - // For environments that do not inherently posses a window with a document - // (such as Node.js), expose a jQuery-making factory as module.exports - // This accentuates the need for the creation of a real window + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. // e.g. var jQuery = require("jquery")(window); - // See ticket #14549 for more info + // See ticket #14549 for more info. module.exports = global.document ? factory( global, true ) : function( w ) { @@ -35,5194 +37,5123 @@ } // Pass this if window is not defined yet -}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { -// Can't do this because several apps including ASP.NET trace -// the stack via arguments.caller.callee and Firefox dies if -// you try to trace through "use strict" call chains. (#13335) -// Support: Firefox 18+ -// +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. + "use strict"; -var deletedIds = []; + var arr = []; -var slice = deletedIds.slice; + var getProto = Object.getPrototypeOf; -var concat = deletedIds.concat; + var slice = arr.slice; + + var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); + } : function( array ) { + return arr.concat.apply( [], array ); + }; -var push = deletedIds.push; -var indexOf = deletedIds.indexOf; + var push = arr.push; -var class2type = {}; + var indexOf = arr.indexOf; -var toString = class2type.toString; + var class2type = {}; -var hasOwn = class2type.hasOwnProperty; + var toString = class2type.toString; -var support = {}; + var hasOwn = class2type.hasOwnProperty; + var fnToString = hasOwn.toString; + var ObjectFunctionString = fnToString.call( Object ); -var - version = "1.11.3", + var support = {}; - // Define a local copy of jQuery - jQuery = function( selector, context ) { - // The jQuery object is actually just the init constructor 'enhanced' - // Need init if jQuery is called (just allow error to be thrown if not included) - return new jQuery.fn.init( selector, context ); - }, + var isFunction = function isFunction( obj ) { - // Support: Android<4.1, IE<9 - // Make sure we trim BOM and NBSP - rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + // Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5 + // Plus for old WebKit, typeof returns "function" for HTML collections + // (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756) + return typeof obj === "function" && typeof obj.nodeType !== "number" && + typeof obj.item !== "function"; + }; - // Matches dashed string for camelizing - rmsPrefix = /^-ms-/, - rdashAlpha = /-([\da-z])/gi, - // Used by jQuery.camelCase as callback to replace() - fcamelCase = function( all, letter ) { - return letter.toUpperCase(); + var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; }; -jQuery.fn = jQuery.prototype = { - // The current version of jQuery being used - jquery: version, - constructor: jQuery, + var document = window.document; - // Start with an empty selector - selector: "", - // The default length of a jQuery object is 0 - length: 0, - toArray: function() { - return slice.call( this ); - }, + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num != null ? + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } - // Return just the one element from the set - ( num < 0 ? this[ num + this.length ] : this[ num ] ) : - // Return all the elements in a clean array - slice.call( this ); - }, + function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems ) { + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; + } + /* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module - // Build a new jQuery matched element set - var ret = jQuery.merge( this.constructor(), elems ); - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - ret.context = this.context; - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - // (You can seed the arguments with an array of args, but this is - // only used internally.) - each: function( callback, args ) { - return jQuery.each( this, callback, args ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map(this, function( elem, i ) { - return callback.call( elem, i, elem ); - })); - }, - - slice: function() { - return this.pushStack( slice.apply( this, arguments ) ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - eq: function( i ) { - var len = this.length, - j = +i + ( i < 0 ? len : 0 ); - return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); - }, - - end: function() { - return this.prevObject || this.constructor(null); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: deletedIds.sort, - splice: deletedIds.splice -}; - -jQuery.extend = jQuery.fn.extend = function() { - var src, copyIsArray, copy, name, options, clone, - target = arguments[0] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - - // skip the boolean and the target - target = arguments[ i ] || {}; - i++; - } + var + version = "3.6.0", - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !jQuery.isFunction(target) ) { - target = {}; - } + // Define a local copy of jQuery + jQuery = function( selector, context ) { - // extend jQuery itself if only one argument is passed - if ( i === length ) { - target = this; - i--; - } + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; - for ( ; i < length; i++ ) { - // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) { - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; + jQuery.fn = jQuery.prototype = { - // Prevent never-ending loop - if ( target === copy ) { - continue; - } + // The current version of jQuery being used + jquery: version, - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { - if ( copyIsArray ) { - copyIsArray = false; - clone = src && jQuery.isArray(src) ? src : []; + constructor: jQuery, - } else { - clone = src && jQuery.isPlainObject(src) ? src : {}; - } + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); } - } - } - // Return the modified object - return target; -}; + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, -jQuery.extend({ - // Unique for each copy of jQuery on the page - expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { - // Assume jQuery is ready without the ready module - isReady: true, + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); - error: function( msg ) { - throw new Error( msg ); - }, + // Add the old object onto the stack (as a reference) + ret.prevObject = this; - noop: function() {}, + // Return the newly-formed element set + return ret; + }, - // See test/unit/core.js for details concerning isFunction. - // Since version 1.3, DOM methods and functions like alert - // aren't supported. They return false on IE (#2968). - isFunction: function( obj ) { - return jQuery.type(obj) === "function"; - }, + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, - isArray: Array.isArray || function( obj ) { - return jQuery.type(obj) === "array"; - }, + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, - isWindow: function( obj ) { - /* jshint eqeqeq: false */ - return obj != null && obj == obj.window; - }, + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, - isNumeric: function( obj ) { - // parseFloat NaNs numeric-cast false positives (null|true|false|"") - // ...but misinterprets leading-number strings, particularly hex literals ("0x...") - // subtraction forces infinities to NaN - // adding 1 corrects loss of precision from parseFloat (#15100) - return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0; - }, + first: function() { + return this.eq( 0 ); + }, - isEmptyObject: function( obj ) { - var name; - for ( name in obj ) { - return false; - } - return true; - }, + last: function() { + return this.eq( -1 ); + }, - isPlainObject: function( obj ) { - var key; + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, - // Must be an Object. - // Because of IE, we also have to check the presence of the constructor property. - // Make sure that DOM nodes and window objects don't pass through, as well - if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { - return false; - } + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, - try { - // Not own constructor property must be Object - if ( obj.constructor && - !hasOwn.call(obj, "constructor") && - !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { - return false; - } - } catch ( e ) { - // IE8,9 Will throw exceptions on certain host objects #9897 - return false; - } + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, - // Support: IE<9 - // Handle iteration over inherited properties before own properties. - if ( support.ownLast ) { - for ( key in obj ) { - return hasOwn.call( obj, key ); - } - } + end: function() { + return this.prevObject || this.constructor(); + }, - // Own properties are enumerated firstly, so to speed up, - // if last one is own, then all properties are own. - for ( key in obj ) {} + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice + }; - return key === undefined || hasOwn.call( obj, key ); - }, + jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; - type: function( obj ) { - if ( obj == null ) { - return obj + ""; + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; } - return typeof obj === "object" || typeof obj === "function" ? - class2type[ toString.call(obj) ] || "object" : - typeof obj; - }, - - // Evaluates a script in a global context - // Workarounds based on findings by Jim Driscoll - // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context - globalEval: function( data ) { - if ( data && jQuery.trim( data ) ) { - // We use execScript on Internet Explorer - // We use an anonymous function so that context is window - // rather than jQuery in Firefox - ( window.execScript || function( data ) { - window[ "eval" ].call( window, data ); - } )( data ); - } - }, - - // Convert dashed to camelCase; used by the css and data modules - // Microsoft forgot to hump their vendor prefix (#9572) - camelCase: function( string ) { - return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); - }, - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); - }, + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } - // args is for internal usage only - each: function( obj, callback, args ) { - var value, - i = 0, - length = obj.length, - isArray = isArraylike( obj ); + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } - if ( args ) { - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback.apply( obj[ i ], args ); + for ( ; i < length; i++ ) { - if ( value === false ) { - break; - } - } - } else { - for ( i in obj ) { - value = callback.apply( obj[ i ], args ); + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { - if ( value === false ) { - break; + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; } - } - } - // A special, fast, case for the most common use of each - } else { - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback.call( obj[ i ], i, obj[ i ] ); + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; - if ( value === false ) { - break; - } - } - } else { - for ( i in obj ) { - value = callback.call( obj[ i ], i, obj[ i ] ); + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; - if ( value === false ) { - break; + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; } } } } - return obj; - }, + // Return the modified object + return target; + }; - // Support: Android<4.1, IE<9 - trim: function( text ) { - return text == null ? - "" : - ( text + "" ).replace( rtrim, "" ); - }, + jQuery.extend( { - // results is for internal usage only - makeArray: function( arr, results ) { - var ret = results || []; + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), - if ( arr != null ) { - if ( isArraylike( Object(arr) ) ) { - jQuery.merge( ret, - typeof arr === "string" ? - [ arr ] : arr - ); - } else { - push.call( ret, arr ); - } - } + // Assume jQuery is ready without the ready module + isReady: true, - return ret; - }, + error: function( msg ) { + throw new Error( msg ); + }, - inArray: function( elem, arr, i ) { - var len; + noop: function() {}, - if ( arr ) { - if ( indexOf ) { - return indexOf.call( arr, elem, i ); + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; } - len = arr.length; - i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + proto = getProto( obj ); - for ( ; i < len; i++ ) { - // Skip accessing in sparse arrays - if ( i in arr && arr[ i ] === elem ) { - return i; - } + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; } - } - - return -1; - }, - merge: function( first, second ) { - var len = +second.length, - j = 0, - i = first.length; + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, - while ( j < len ) { - first[ i++ ] = second[ j++ ]; - } + isEmptyObject: function( obj ) { + var name; - // Support: IE<9 - // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists) - if ( len !== len ) { - while ( second[j] !== undefined ) { - first[ i++ ] = second[ j++ ]; + for ( name in obj ) { + return false; } - } + return true; + }, - first.length = i; + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, - return first; - }, + each: function( obj, callback ) { + var length, i = 0; - grep: function( elems, callback, invert ) { - var callbackInverse, - matches = [], - i = 0, - length = elems.length, - callbackExpect = !invert; + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } - // Go through the array, only saving the items - // that pass the validator function - for ( ; i < length; i++ ) { - callbackInverse = !callback( elems[ i ], i ); - if ( callbackInverse !== callbackExpect ) { - matches.push( elems[ i ] ); + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } } - } - return matches; - }, + return ret; + }, - // arg is for internal usage only - map: function( elems, callback, arg ) { - var value, - i = 0, - length = elems.length, - isArray = isArraylike( elems ), - ret = []; + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, - // Go through the array, translating each of the items to their new values - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; - if ( value != null ) { - ret.push( value ); - } + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; } - // Go through every key on the object, - } else { - for ( i in elems ) { - value = callback( elems[ i ], i, arg ); + first.length = i; + + return first; + }, - if ( value != null ) { - ret.push( value ); + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); } } - } - // Flatten any nested arrays - return concat.apply( [], ret ); - }, + return matches; + }, - // A global GUID counter for objects - guid: 1, + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; - // Bind a function to a context, optionally partially applying any - // arguments. - proxy: function( fn, context ) { - var args, proxy, tmp; + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); - if ( typeof context === "string" ) { - tmp = fn[ context ]; - context = fn; - fn = tmp; - } + if ( value != null ) { + ret.push( value ); + } + } - // Quick check to determine if target is callable, in the spec - // this throws a TypeError, but we will just return undefined. - if ( !jQuery.isFunction( fn ) ) { - return undefined; - } + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); - // Simulated bind - args = slice.call( arguments, 2 ); - proxy = function() { - return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); - }; + if ( value != null ) { + ret.push( value ); + } + } + } - // Set the guid of unique handler to the same of original handler, so it can be removed - proxy.guid = fn.guid = fn.guid || jQuery.guid++; + // Flatten any nested arrays + return flat( ret ); + }, - return proxy; - }, + // A global GUID counter for objects + guid: 1, - now: function() { - return +( new Date() ); - }, + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support + } ); - // jQuery.support is not used in Core but other projects attach their - // properties to it so it needs to exist. - support: support -}); + if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; + } // Populate the class2type map -jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -}); + jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), + function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); + } ); -function isArraylike( obj ) { + function isArrayLike( obj ) { - // Support: iOS 8.2 (not reproducible in simulator) - // `in` check used to prevent JIT error (gh-2145) - // hasOwn isn't used here due to false negatives - // regarding Nodelist length in IE - var length = "length" in obj && obj.length, - type = jQuery.type( obj ); + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); - if ( type === "function" || jQuery.isWindow( obj ) ) { - return false; - } + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } - if ( obj.nodeType === 1 && length ) { - return true; + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; } - - return type === "array" || length === 0 || - typeof length === "number" && length > 0 && ( length - 1 ) in obj; -} -var Sizzle = -/*! - * Sizzle CSS Selector Engine v2.2.0-pre - * http://sizzlejs.com/ + var Sizzle = + /*! + * Sizzle CSS Selector Engine v2.3.6 + * https://sizzlejs.com/ * - * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors + * Copyright JS Foundation and other contributors * Released under the MIT license - * http://jquery.org/license + * https://js.foundation/ * - * Date: 2014-12-16 + * Date: 2021-02-16 */ -(function( window ) { - -var i, - support, - Expr, - getText, - isXML, - tokenize, - compile, - select, - outermostContext, - sortInput, - hasDuplicate, - - // Local document vars - setDocument, - document, - docElem, - documentIsHTML, - rbuggyQSA, - rbuggyMatches, - matches, - contains, - - // Instance-specific data - expando = "sizzle" + 1 * new Date(), - preferredDoc = window.document, - dirruns = 0, - done = 0, - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - } - return 0; - }, - - // General-purpose constants - MAX_NEGATIVE = 1 << 31, - - // Instance methods - hasOwn = ({}).hasOwnProperty, - arr = [], - pop = arr.pop, - push_native = arr.push, - push = arr.push, - slice = arr.slice, - // Use a stripped-down indexOf as it's faster than native - // http://jsperf.com/thor-indexof-vs-for/5 - indexOf = function( list, elem ) { - var i = 0, - len = list.length; - for ( ; i < len; i++ ) { - if ( list[i] === elem ) { - return i; - } - } - return -1; - }, - - booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", - - // Regular expressions - - // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - // http://www.w3.org/TR/css3-syntax/#characters - characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", - - // Loosely modeled on CSS identifier characters - // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors - // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = characterEncoding.replace( "w", "w#" ), - - // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors - attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace + - // Operator (capture 2) - "*([*^$|!~]?=)" + whitespace + - // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" - "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + - "*\\]", - - pseudos = ":(" + characterEncoding + ")(?:\\((" + - // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: - // 1. quoted (capture 3; capture 4 or capture 5) - "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + - // 2. simple (capture 6) - "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + - // 3. anything else (capture 2) - ".*" + - ")\\)|)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rwhitespace = new RegExp( whitespace + "+", "g" ), - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), - - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), - - rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), - - rpseudo = new RegExp( pseudos ), - ridentifier = new RegExp( "^" + identifier + "$" ), - - matchExpr = { - "ID": new RegExp( "^#(" + characterEncoding + ")" ), - "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), - "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), - // For use in libraries implementing .is() - // We use this for POS matching in `select` - "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + - whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) - }, - - rinputs = /^(?:input|select|textarea|button)$/i, - rheader = /^h\d$/i, - - rnative = /^[^{]+\{\s*\[native \w/, - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, - - rsibling = /[+~]/, - rescape = /'|\\/g, - - // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters - runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), - funescape = function( _, escaped, escapedWhitespace ) { - var high = "0x" + escaped - 0x10000; - // NaN means non-codepoint - // Support: Firefox<24 - // Workaround erroneous numeric interpretation of +"0x" - return high !== high || escapedWhitespace ? - escaped : - high < 0 ? - // BMP codepoint - String.fromCharCode( high + 0x10000 ) : - // Supplemental Plane codepoint (surrogate pair) - String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); - }, - - // Used for iframes - // See setDocument() - // Removing the function wrapper causes a "Permission Denied" - // error in IE - unloadHandler = function() { - setDocument(); - }; + ( function( window ) { + var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, -// Optimize for push.apply( _, NodeList ) -try { - push.apply( - (arr = slice.call( preferredDoc.childNodes )), - preferredDoc.childNodes - ); - // Support: Android<4.0 - // Detect silently failing push.apply - arr[ preferredDoc.childNodes.length ].nodeType; -} catch ( e ) { - push = { apply: arr.length ? - - // Leverage slice if possible - function( target, els ) { - push_native.apply( target, slice.call(els) ); - } : - - // Support: IE<9 - // Otherwise append directly - function( target, els ) { - var j = target.length, - i = 0; - // Can't trust NodeList.length - while ( (target[j++] = els[i++]) ) {} - target.length = j - 1; - } - }; -} + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, -function Sizzle( selector, context, results, seed ) { - var match, elem, m, nodeType, - // QSA vars - i, groups, old, nid, newContext, newSelector; + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", - if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { - setDocument( context ); - } + // Regular expressions - context = context || document; - results = results || []; - nodeType = context.nodeType; + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", - if ( typeof selector !== "string" || !selector || - nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", - return results; - } + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + - if ( !seed && documentIsHTML ) { - - // Try to shortcut find operations when possible (e.g., not under DocumentFragment) - if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { - // Speed-up: Sizzle("#ID") - if ( (m = match[1]) ) { - if ( nodeType === 9 ) { - elem = context.getElementById( m ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document (jQuery #6963) - if ( elem && elem.parentNode ) { - // Handle the case where IE, Opera, and Webkit return items - // by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - } else { - // Context is not a document - if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && - contains( context, elem ) && elem.id === m ) { - results.push( elem ); - return results; - } - } + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + - // Speed-up: Sizzle("TAG") - } else if ( match[2] ) { - push.apply( results, context.getElementsByTagName( selector ) ); - return results; + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", - // Speed-up: Sizzle(".CLASS") - } else if ( (m = match[3]) && support.getElementsByClassName ) { - push.apply( results, context.getElementsByClassName( m ) ); - return results; - } - } + pseudos = ":(" + identifier + ")(?:\\((" + - // QSA path - if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { - nid = old = expando; - newContext = context; - newSelector = nodeType !== 1 && selector; + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { - groups = tokenize( selector ); + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + - if ( (old = context.getAttribute("id")) ) { - nid = old.replace( rescape, "\\$&" ); - } else { - context.setAttribute( "id", nid ); - } - nid = "[id='" + nid + "'] "; + // 3. anything else (capture 2) + ".*" + + ")\\)|)", - i = groups.length; - while ( i-- ) { - groups[i] = nid + toSelector( groups[i] ); - } - newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context; - newSelector = groups.join(","); - } + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), - if ( newSelector ) { - try { - push.apply( results, - newContext.querySelectorAll( newSelector ) - ); - return results; - } catch(qsaError) { - } finally { - if ( !old ) { - context.removeAttribute("id"); - } - } - } - } - } + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), - // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed ); -} + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), -/** - * Create key-value caches of limited size - * @returns {Function(string, Object)} Returns the Object data after storing it on itself with - * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) - * deleting the oldest entry - */ -function createCache() { - var keys = []; + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), - function cache( key, value ) { - // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) - if ( keys.push( key + " " ) > Expr.cacheLength ) { - // Only keep the most recent entries - delete cache[ keys.shift() ]; - } - return (cache[ key + " " ] = value); - } - return cache; -} + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, -/** - * Mark a function for special use by Sizzle - * @param {Function} fn The function to mark - */ -function markFunction( fn ) { - fn[ expando ] = true; - return fn; -} - -/** - * Support testing using an element - * @param {Function} fn Passed the created div and expects a boolean result - */ -function assert( fn ) { - var div = document.createElement("div"); + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, - try { - return !!fn( div ); - } catch (e) { - return false; - } finally { - // Remove from its parent by default - if ( div.parentNode ) { - div.parentNode.removeChild( div ); - } - // release memory in IE - div = null; - } -} + rnative = /^[^{]+\{\s*\[native \w/, -/** - * Adds the same handler for all of the specified attrs - * @param {String} attrs Pipe-separated list of attributes - * @param {Function} handler The method that will be applied - */ -function addHandle( attrs, handler ) { - var arr = attrs.split("|"), - i = attrs.length; + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, - while ( i-- ) { - Expr.attrHandle[ arr[i] ] = handler; - } -} + rsibling = /[+~]/, -/** - * Checks document order of two siblings - * @param {Element} a - * @param {Element} b - * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b - */ -function siblingCheck( a, b ) { - var cur = b && a, - diff = cur && a.nodeType === 1 && b.nodeType === 1 && - ( ~b.sourceIndex || MAX_NEGATIVE ) - - ( ~a.sourceIndex || MAX_NEGATIVE ); - - // Use IE sourceIndex if available on both nodes - if ( diff ) { - return diff; - } + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; - // Check if b follows a - if ( cur ) { - while ( (cur = cur.nextSibling) ) { - if ( cur === b ) { - return -1; - } - } - } + return nonHex ? - return a ? 1 : -1; -} + // Strip the backslash prefix from a non-hex escape sequence + nonHex : -/** - * Returns a function to use in pseudos for input types - * @param {String} type - */ -function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; -} + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, -/** - * Returns a function to use in pseudos for buttons - * @param {String} type - */ -function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; - }; -} + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { -/** - * Returns a function to use in pseudos for positionals - * @param {Function} fn - */ -function createPositionalPseudo( fn ) { - return markFunction(function( argument ) { - argument = +argument; - return markFunction(function( seed, matches ) { - var j, - matchIndexes = fn( [], seed.length, argument ), - i = matchIndexes.length; - - // Match elements found at the specified indexes - while ( i-- ) { - if ( seed[ (j = matchIndexes[i]) ] ) { - seed[j] = !(matches[j] = seed[j]); - } - } - }); - }); -} + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } -/** - * Checks a node for validity as a Sizzle context - * @param {Element|Object=} context - * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value - */ -function testContext( context ) { - return context && typeof context.getElementsByTagName !== "undefined" && context; -} - -// Expose support vars for convenience -support = Sizzle.support = {}; - -/** - * Detects XML nodes - * @param {Element|Object} elem An element or a document - * @returns {Boolean} True iff elem is a non-HTML XML node - */ -isXML = Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = elem && (elem.ownerDocument || elem).documentElement; - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -/** - * Sets document-related variables once based on the current document - * @param {Element|Object} [doc] An element or document object to use to set the document - * @returns {Object} Returns the current document - */ -setDocument = Sizzle.setDocument = function( node ) { - var hasCompare, parent, - doc = node ? node.ownerDocument || node : preferredDoc; - - // If no document and documentElement is available, return - if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { - return document; - } - - // Set our document - document = doc; - docElem = doc.documentElement; - parent = doc.defaultView; - - // Support: IE>8 - // If iframe document is assigned to "document" variable and if iframe has been reloaded, - // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 - // IE6-8 do not support the defaultView property so parent will be undefined - if ( parent && parent !== parent.top ) { - // IE11 does not have attachEvent, so all must suffer - if ( parent.addEventListener ) { - parent.addEventListener( "unload", unloadHandler, false ); - } else if ( parent.attachEvent ) { - parent.attachEvent( "onunload", unloadHandler ); - } - } + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } - /* Support tests - ---------------------------------------------------------------------- */ - documentIsHTML = !isXML( doc ); + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, - /* Attributes - ---------------------------------------------------------------------- */ + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, - // Support: IE<8 - // Verify that getAttribute really returns attributes and not properties - // (excepting IE8 booleans) - support.attributes = assert(function( div ) { - div.className = "i"; - return !div.getAttribute("className"); - }); + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); - /* getElement(s)By* - ---------------------------------------------------------------------- */ +// Optimize for push.apply( _, NodeList ) + try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); - // Check if getElementsByTagName("*") returns only elements - support.getElementsByTagName = assert(function( div ) { - div.appendChild( doc.createComment("") ); - return !div.getElementsByTagName("*").length; - }); - - // Support: IE<9 - support.getElementsByClassName = rnative.test( doc.getElementsByClassName ); - - // Support: IE<10 - // Check if getElementById returns elements by name - // The broken getElementById methods don't pick up programatically-set names, - // so use a roundabout getElementsByName test - support.getById = assert(function( div ) { - docElem.appendChild( div ).id = expando; - return !doc.getElementsByName || !doc.getElementsByName( expando ).length; - }); - - // ID find and filter - if ( support.getById ) { - Expr.find["ID"] = function( id, context ) { - if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { - var m = context.getElementById( id ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [ m ] : []; - } - }; - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - return elem.getAttribute("id") === attrId; - }; - }; - } else { - // Support: IE6/7 - // getElementById is not reliable as a find shortcut - delete Expr.find["ID"]; - - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); - return node && node.value === attrId; - }; - }; - } + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; + } catch ( e ) { + push = { apply: arr.length ? - // Tag - Expr.find["TAG"] = support.getElementsByTagName ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== "undefined" ) { - return context.getElementsByTagName( tag ); + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : - // DocumentFragment nodes don't have gEBTN - } else if ( support.qsa ) { - return context.querySelectorAll( tag ); + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; } - } : - - function( tag, context ) { - var elem, - tmp = [], - i = 0, - // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too - results = context.getElementsByTagName( tag ); - // Filter out possible comments - if ( tag === "*" ) { - while ( (elem = results[i++]) ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } + function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, - return tmp; - } - return results; - }; + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; - // Class - Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { - if ( documentIsHTML ) { - return context.getElementsByClassName( className ); - } - }; + results = results || []; - /* QSA/matchesSelector - ---------------------------------------------------------------------- */ + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { - // QSA and matchesSelector support + return results; + } - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - rbuggyMatches = []; + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } - // qSa(:focus) reports false when true (Chrome 21) - // We allow this because of a bug in IE8/9 that throws an error - // whenever `document.activeElement` is accessed on an iframe - // So, we allow :focus to pass through QSA all the time to avoid the IE error - // See http://bugs.jquery.com/ticket/13378 - rbuggyQSA = []; + // Element context + } else { - if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert(function( div ) { - // Select is set to empty string on purpose - // This is to test IE's treatment of not explicitly - // setting a boolean content attribute, - // since its presence should be enough - // http://bugs.jquery.com/ticket/12359 - docElem.appendChild( div ).innerHTML = "" + - ""; + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { - // Support: IE8, Opera 11-12.16 - // Nothing should be selected when empty strings follow ^= or $= or *= - // The test attribute must be unknown in Opera but "safe" for WinRT - // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section - if ( div.querySelectorAll("[msallowcapture^='']").length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); - } + results.push( elem ); + return results; + } + } - // Support: IE8 - // Boolean attributes and "value" are not treated correctly - if ( !div.querySelectorAll("[selected]").length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); - } + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; - // Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+ - if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) { - rbuggyQSA.push("~="); - } + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here and will not see later tests - if ( !div.querySelectorAll(":checked").length ) { - rbuggyQSA.push(":checked"); - } + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } - // Support: Safari 8+, iOS 8+ - // https://bugs.webkit.org/show_bug.cgi?id=136851 - // In-page `selector#id sibing-combinator selector` fails - if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) { - rbuggyQSA.push(".#.+[+~]"); - } - }); + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } - assert(function( div ) { - // Support: Windows 8 Native Apps - // The type and name attributes are restricted during .innerHTML assignment - var input = doc.createElement("input"); - input.setAttribute( "type", "hidden" ); - div.appendChild( input ).setAttribute( "name", "D" ); + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } - // Support: IE8 - // Enforce case-sensitivity of name attribute - if ( div.querySelectorAll("[name=d]").length ) { - rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); - } + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here and will not see later tests - if ( !div.querySelectorAll(":enabled").length ) { - rbuggyQSA.push( ":enabled", ":disabled" ); + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); } - // Opera 10-11 does not throw on post-comma invalid pseudos - div.querySelectorAll("*,:x"); - rbuggyQSA.push(",.*:"); - }); - } + /** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ + function createCache() { + var keys = []; - if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || - docElem.webkitMatchesSelector || - docElem.mozMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector) )) ) { - - assert(function( div ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - support.disconnectedMatch = matches.call( div, "div" ); - - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( div, "[s!='']:x" ); - rbuggyMatches.push( "!=", pseudos ); - }); - } + function cache( key, value ) { - rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); - rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { - /* Contains - ---------------------------------------------------------------------- */ - hasCompare = rnative.test( docElem.compareDocumentPosition ); - - // Element contains another - // Purposefully does not implement inclusive descendent - // As in, an element does not contain itself - contains = hasCompare || rnative.test( docElem.contains ) ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && ( - adown.contains ? - adown.contains( bup ) : - a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 - )); - } : - function( a, b ) { - if ( b ) { - while ( (b = b.parentNode) ) { - if ( b === a ) { - return true; + // Only keep the most recent entries + delete cache[ keys.shift() ]; } + return ( cache[ key + " " ] = value ); } + return cache; } - return false; - }; - - /* Sorting - ---------------------------------------------------------------------- */ - - // Document order sorting - sortOrder = hasCompare ? - function( a, b ) { - - // Flag for duplicate removal - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - // Sort on method existence if only one input has compareDocumentPosition - var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; - if ( compare ) { - return compare; - } - // Calculate position if both inputs belong to the same document - compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? - a.compareDocumentPosition( b ) : - - // Otherwise we know they are disconnected - 1; - - // Disconnected nodes - if ( compare & 1 || - (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { - - // Choose the first element that is related to our preferred document - if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { - return -1; - } - if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { - return 1; + /** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ + function markFunction( fn ) { + fn[ expando ] = true; + return fn; } - // Maintain original order - return sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : - 0; - } - - return compare & 4 ? -1 : 1; - } : - function( a, b ) { - // Exit early if the nodes are identical - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - var cur, - i = 0, - aup = a.parentNode, - bup = b.parentNode, - ap = [ a ], - bp = [ b ]; - - // Parentless nodes are either documents or disconnected - if ( !aup || !bup ) { - return a === doc ? -1 : - b === doc ? 1 : - aup ? -1 : - bup ? 1 : - sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : - 0; - - // If the nodes are siblings, we can do a quick check - } else if ( aup === bup ) { - return siblingCheck( a, b ); - } - - // Otherwise we need full lists of their ancestors for comparison - cur = a; - while ( (cur = cur.parentNode) ) { - ap.unshift( cur ); - } - cur = b; - while ( (cur = cur.parentNode) ) { - bp.unshift( cur ); - } - - // Walk down the tree looking for a discrepancy - while ( ap[i] === bp[i] ) { - i++; - } - - return i ? - // Do a sibling check if the nodes have a common ancestor - siblingCheck( ap[i], bp[i] ) : + /** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ + function assert( fn ) { + var el = document.createElement( "fieldset" ); - // Otherwise nodes in our document sort first - ap[i] === preferredDoc ? -1 : - bp[i] === preferredDoc ? 1 : - 0; - }; + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { - return doc; -}; + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } -Sizzle.matches = function( expr, elements ) { - return Sizzle( expr, null, null, elements ); -}; + // release memory in IE + el = null; + } + } -Sizzle.matchesSelector = function( elem, expr ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } + /** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ + function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; - // Make sure that attribute selectors are quoted - expr = expr.replace( rattributeQuotes, "='$1']" ); + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } + } - if ( support.matchesSelector && documentIsHTML && - ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && - ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + /** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ + function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } - try { - var ret = matches.call( elem, expr ); + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || support.disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { - return ret; + return a ? 1 : -1; } - } catch (e) {} - } - return Sizzle( expr, document, null, [ elem ] ).length > 0; -}; + /** + * Returns a function to use in pseudos for input types + * @param {String} type + */ + function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; + } -Sizzle.contains = function( context, elem ) { - // Set document vars if needed - if ( ( context.ownerDocument || context ) !== document ) { - setDocument( context ); - } - return contains( context, elem ); -}; + /** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ + function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; + } -Sizzle.attr = function( elem, name ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } + /** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ + function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } - var fn = Expr.attrHandle[ name.toLowerCase() ], - // Don't get fooled by Object.prototype properties (jQuery #13807) - val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? - fn( elem, name, !documentIsHTML ) : - undefined; - - return val !== undefined ? - val : - support.attributes || !documentIsHTML ? - elem.getAttribute( name ) : - (val = elem.getAttributeNode(name)) && val.specified ? - val.value : - null; -}; + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } -/** - * Document sorting and removing duplicates - * @param {ArrayLike} results - */ -Sizzle.uniqueSort = function( results ) { - var elem, - duplicates = [], - j = 0, - i = 0; + return elem.disabled === disabled; - // Unless we *know* we can detect duplicates, assume their presence - hasDuplicate = !support.detectDuplicates; - sortInput = !support.sortStable && results.slice( 0 ); - results.sort( sortOrder ); + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } - if ( hasDuplicate ) { - while ( (elem = results[i++]) ) { - if ( elem === results[ i ] ) { - j = duplicates.push( i ); + // Remaining elements are neither :enabled nor :disabled + return false; + }; } - } - while ( j-- ) { - results.splice( duplicates[ j ], 1 ); - } - } - // Clear input after sorting to release objects - // See https://github.com/jquery/sizzle/pull/225 - sortInput = null; + /** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ + function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; - return results; -}; + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); + } -/** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -getText = Sizzle.getText = function( elem ) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if ( !nodeType ) { - // If no nodeType, this is expected to be an array - while ( (node = elem[i++]) ) { - // Do not traverse comment nodes - ret += getText( node ); - } - } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - // Use textContent for elements - // innerText usage removed for consistency of new lines (jQuery #11153) - if ( typeof elem.textContent === "string" ) { - return elem.textContent; - } else { - // Traverse its children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - ret += getText( elem ); + /** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ + function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - // Do not include comment or processing instruction nodes - return ret; -}; +// Expose support vars for convenience + support = Sizzle.support = {}; + + /** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ + isXML = Sizzle.isXML = function( elem ) { + var namespace = elem && elem.namespaceURI, + docElem = elem && ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); + }; -Expr = Sizzle.selectors = { + /** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ + setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } - // Can be adjusted by the user - cacheLength: 50, + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } - createPseudo: markFunction, + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ - match: matchExpr, + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ - attrHandle: {}, + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; - find: {}, + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, + if ( elem ) { - preFilter: { - "ATTR": function( match ) { - match[1] = match[1].replace( runescape, funescape ); + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } - // Move the given value to match[3] whether quoted or unquoted - match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } - if ( match[2] === "~=" ) { - match[3] = " " + match[3] + " "; - } + return []; + } + }; + } - return match.slice( 0, 4 ); - }, + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); - "CHILD": function( match ) { - /* matches from matchExpr["CHILD"] - 1 type (only|nth|...) - 2 what (child|of-type) - 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 4 xn-component of xn+y argument ([+-]?\d*n|) - 5 sign of xn-component - 6 x of xn-component - 7 sign of y-component - 8 y of y-component - */ - match[1] = match[1].toLowerCase(); + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : - if ( match[1].slice( 0, 3 ) === "nth" ) { - // nth-* requires argument - if ( !match[3] ) { - Sizzle.error( match[0] ); - } + function( tag, context ) { + var elem, + tmp = [], + i = 0, - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); - match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); - // other types prohibit arguments - } else if ( match[3] ) { - Sizzle.error( match[0] ); - } + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } - return match; - }, + return tmp; + } + return results; + }; - "PSEUDO": function( match ) { - var excess, - unquoted = !match[6] && match[2]; + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; - if ( matchExpr["CHILD"].test( match[0] ) ) { - return null; - } + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ - // Accept quoted arguments as-is - if ( match[3] ) { - match[2] = match[4] || match[5] || ""; + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } - // Strip excess characters from unquoted arguments - } else if ( unquoted && rpseudo.test( unquoted ) && - // Get excess from tokenize (recursively) - (excess = tokenize( unquoted, true )) && - // advance to the next closing parenthesis - (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } - // excess is a negative index - match[0] = match[0].slice( 0, excess ); - match[2] = unquoted.slice( 0, excess ); - } + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } - // Return only captures needed by the pseudo filter method (type and argument) - return match.slice( 0, 3 ); - } - }, + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } - filter: { + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } - "TAG": function( nodeNameSelector ) { - var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); - return nodeNameSelector === "*" ? - function() { return true; } : - function( elem ) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; - }, + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } - "CLASS": function( className ) { - var pattern = classCache[ className + " " ]; + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } - return pattern || - (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && - classCache( className, function( elem ) { - return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); - }); - }, + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } - "ATTR": function( name, operator, check ) { - return function( elem ) { - var result = Sizzle.attr( elem, name ); + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } - if ( result == null ) { - return operator === "!="; - } - if ( !operator ) { - return true; + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); } - result += ""; + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { - return operator === "=" ? result === check : - operator === "!=" ? result !== check : - operator === "^=" ? check && result.indexOf( check ) === 0 : - operator === "*=" ? check && result.indexOf( check ) > -1 : - operator === "$=" ? check && result.slice( -check.length ) === check : - operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : - operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : - false; - }; - }, - - "CHILD": function( type, what, argument, first, last ) { - var simple = type.slice( 0, 3 ) !== "nth", - forward = type.slice( -4 ) !== "last", - ofType = what === "of-type"; - - return first === 1 && last === 0 ? + assert( function( el ) { - // Shortcut for :nth-*(n) - function( elem ) { - return !!elem.parentNode; - } : + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); - function( elem, context, xml ) { - var cache, outerCache, node, diff, nodeIndex, start, - dir = simple !== forward ? "nextSibling" : "previousSibling", - parent = elem.parentNode, - name = ofType && elem.nodeName.toLowerCase(), - useCache = !xml && !ofType; + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } - if ( parent ) { + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); - // :(first|last|only)-(child|of-type) - if ( simple ) { - while ( dir ) { - node = elem; - while ( (node = node[ dir ]) ) { - if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { - return false; - } + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; } - // Reverse direction for :only-* (if we haven't yet done so) - start = dir = type === "only" && !start && "nextSibling"; } - return true; } + return false; + }; - start = [ forward ? parent.firstChild : parent.lastChild ]; + /* Sorting + ---------------------------------------------------------------------- */ - // non-xml :nth-child(...) stores cache data on `parent` - if ( forward && useCache ) { - // Seek `elem` from a previously-cached index - outerCache = parent[ expando ] || (parent[ expando ] = {}); - cache = outerCache[ type ] || []; - nodeIndex = cache[0] === dirruns && cache[1]; - diff = cache[0] === dirruns && cache[2]; - node = nodeIndex && parent.childNodes[ nodeIndex ]; + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { - while ( (node = ++nodeIndex && node && node[ dir ] || + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } - // Fallback to seeking `elem` from the start - (diff = nodeIndex = 0) || start.pop()) ) { + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } - // When found, cache indexes on `parent` and break - if ( node.nodeType === 1 && ++diff && node === elem ) { - outerCache[ type ] = [ dirruns, nodeIndex, diff ]; - break; - } + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; } - // Use previously-cached element index if available - } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { - diff = cache[1]; + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } - // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) - } else { - // Use the same loop as above to seek `elem` from the start - while ( (node = ++nodeIndex && node && node[ dir ] || - (diff = nodeIndex = 0) || start.pop()) ) { - - if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { - // Cache the index of each encountered element - if ( useCache ) { - (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; - } + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } - if ( node === elem ) { - break; - } - } - } + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; } - // Incorporate the offset, then check against cycle size - diff -= last; - return diff === first || ( diff % first === 0 && diff / first >= 0 ); - } - }; - }, + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } - "PSEUDO": function( pseudo, argument ) { - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - // Remember that setFilters inherits from pseudos - var args, - fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || - Sizzle.error( "unsupported pseudo: " + pseudo ); - - // The user may use createPseudo to indicate that - // arguments are needed to create the filter function - // just as Sizzle does - if ( fn[ expando ] ) { - return fn( argument ); - } - - // But maintain support for old signatures - if ( fn.length > 1 ) { - args = [ pseudo, pseudo, "", argument ]; - return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? - markFunction(function( seed, matches ) { - var idx, - matched = fn( seed, argument ), - i = matched.length; - while ( i-- ) { - idx = indexOf( seed, matched[i] ); - seed[ idx ] = !( matches[ idx ] = matched[i] ); + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); } - }) : - function( elem ) { - return fn( elem, 0, args ); - }; - } - return fn; - } - }, + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } - pseudos: { - // Potentially complex pseudos - "not": markFunction(function( selector ) { - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var input = [], - results = [], - matcher = compile( selector.replace( rtrim, "$1" ) ); + return i ? - return matcher[ expando ] ? - markFunction(function( seed, matches, context, xml ) { - var elem, - unmatched = matcher( seed, null, xml, [] ), - i = seed.length; + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : - // Match elements unmatched by `matcher` - while ( i-- ) { - if ( (elem = unmatched[i]) ) { - seed[i] = !(matches[i] = elem); - } - } - }) : - function( elem, context, xml ) { - input[0] = elem; - matcher( input, null, xml, results ); - // Don't keep the element (issue #299) - input[0] = null; - return !results.pop(); - }; - }), + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; - "has": markFunction(function( selector ) { - return function( elem ) { - return Sizzle( selector, elem ).length > 0; + return document; }; - }), - "contains": markFunction(function( text ) { - text = text.replace( runescape, funescape ); - return function( elem ) { - return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; - }; - }), - - // "Whether an element is represented by a :lang() selector - // is based solely on the element's language value - // being equal to the identifier C, - // or beginning with the identifier C immediately followed by "-". - // The matching of C against the element's language value is performed case-insensitively. - // The identifier C does not have to be a valid language name." - // http://www.w3.org/TR/selectors/#lang-pseudo - "lang": markFunction( function( lang ) { - // lang value must be a valid identifier - if ( !ridentifier.test(lang || "") ) { - Sizzle.error( "unsupported lang: " + lang ); - } - lang = lang.replace( runescape, funescape ).toLowerCase(); - return function( elem ) { - var elemLang; - do { - if ( (elemLang = documentIsHTML ? - elem.lang : - elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { - - elemLang = elemLang.toLowerCase(); - return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; - } - } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); - return false; + Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); }; - }), - // Miscellaneous - "target": function( elem ) { - var hash = window.location && window.location.hash; - return hash && hash.slice( 1 ) === elem.id; - }, + Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); - "root": function( elem ) { - return elem === docElem; - }, + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { - "focus": function( elem ) { - return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); - }, + try { + var ret = matches.call( elem, expr ); - // Boolean properties - "enabled": function( elem ) { - return elem.disabled === false; - }, + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || - "disabled": function( elem ) { - return elem.disabled === true; - }, + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } - "checked": function( elem ) { - // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); - }, + return Sizzle( expr, document, null, [ elem ] ).length > 0; + }; - "selected": function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } + Sizzle.contains = function( context, elem ) { - return elem.selected === true; - }, + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); + }; - // Contents - "empty": function( elem ) { - // http://www.w3.org/TR/selectors/#empty-pseudo - // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), - // but not by others (comment: 8; processing instruction: 7; etc.) - // nodeType < 6 works because attributes (2) do not appear as children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - if ( elem.nodeType < 6 ) { - return false; + Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); } - } - return true; - }, - "parent": function( elem ) { - return !Expr.pseudos["empty"]( elem ); - }, + var fn = Expr.attrHandle[ name.toLowerCase() ], - // Element/input types - "header": function( elem ) { - return rheader.test( elem.nodeName ); - }, + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; - "input": function( elem ) { - return rinputs.test( elem.nodeName ); - }, + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + }; - "button": function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; - }, + Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); + }; - "text": function( elem ) { - var attr; - return elem.nodeName.toLowerCase() === "input" && - elem.type === "text" && + Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); + }; - // Support: IE<8 - // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" - ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); - }, + /** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ + Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } - // Position-in-collection - "first": createPositionalPseudo(function() { - return [ 0 ]; - }), + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; - "last": createPositionalPseudo(function( matchIndexes, length ) { - return [ length - 1 ]; - }), + return results; + }; - "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ argument < 0 ? argument + length : argument ]; - }), + /** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ + getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; - "even": createPositionalPseudo(function( matchIndexes, length ) { - var i = 0; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), + if ( !nodeType ) { - "odd": createPositionalPseudo(function( matchIndexes, length ) { - var i = 1; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { - "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; --i >= 0; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; ++i < length; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }) - } -}; + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { -Expr.pseudos["nth"] = Expr.pseudos["eq"]; + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } -// Add button/input type pseudos -for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { - Expr.pseudos[ i ] = createInputPseudo( i ); -} -for ( i in { submit: true, reset: true } ) { - Expr.pseudos[ i ] = createButtonPseudo( i ); -} + // Do not include comment or processing instruction nodes -// Easy API for creating new setFilters -function setFilters() {} -setFilters.prototype = Expr.filters = Expr.pseudos; -Expr.setFilters = new setFilters(); + return ret; + }; -tokenize = Sizzle.tokenize = function( selector, parseOnly ) { - var matched, match, tokens, type, - soFar, groups, preFilters, - cached = tokenCache[ selector + " " ]; + Expr = Sizzle.selectors = { - if ( cached ) { - return parseOnly ? 0 : cached.slice( 0 ); - } + // Can be adjusted by the user + cacheLength: 50, - soFar = selector; - groups = []; - preFilters = Expr.preFilter; + createPseudo: markFunction, - while ( soFar ) { + match: matchExpr, - // Comma and first run - if ( !matched || (match = rcomma.exec( soFar )) ) { - if ( match ) { - // Don't consume trailing commas as valid - soFar = soFar.slice( match[0].length ) || soFar; - } - groups.push( (tokens = []) ); - } + attrHandle: {}, - matched = false; + find: {}, - // Combinators - if ( (match = rcombinators.exec( soFar )) ) { - matched = match.shift(); - tokens.push({ - value: matched, - // Cast descendant combinators to space - type: match[0].replace( rtrim, " " ) - }); - soFar = soFar.slice( matched.length ); - } + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, - // Filters - for ( type in Expr.filter ) { - if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || - (match = preFilters[ type ]( match ))) ) { - matched = match.shift(); - tokens.push({ - value: matched, - type: type, - matches: match - }); - soFar = soFar.slice( matched.length ); - } - } + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); - if ( !matched ) { - break; - } - } + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); - // Return the length of the invalid excess - // if we're just parsing - // Otherwise, throw an error or return tokens - return parseOnly ? - soFar.length : - soFar ? - Sizzle.error( selector ) : - // Cache the tokens - tokenCache( selector, groups ).slice( 0 ); -}; - -function toSelector( tokens ) { - var i = 0, - len = tokens.length, - selector = ""; - for ( ; i < len; i++ ) { - selector += tokens[i].value; - } - return selector; -} - -function addCombinator( matcher, combinator, base ) { - var dir = combinator.dir, - checkNonElements = base && dir === "parentNode", - doneName = done++; - - return combinator.first ? - // Check against closest ancestor/preceding element - function( elem, context, xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - return matcher( elem, context, xml ); - } - } - } : - - // Check against all ancestor/preceding elements - function( elem, context, xml ) { - var oldCache, outerCache, - newCache = [ dirruns, doneName ]; - - // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching - if ( xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - if ( matcher( elem, context, xml ) ) { - return true; + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; } - } - } - } else { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - outerCache = elem[ expando ] || (elem[ expando ] = {}); - if ( (oldCache = outerCache[ dir ]) && - oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { - - // Assign to newCache so results back-propagate to previous elements - return (newCache[ 2 ] = oldCache[ 2 ]); - } else { - // Reuse newcache so results back-propagate to previous elements - outerCache[ dir ] = newCache; - // A match means we're done; a fail means we have to keep checking - if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { - return true; - } - } - } - } - } - }; -} + return match.slice( 0, 4 ); + }, -function elementMatcher( matchers ) { - return matchers.length > 1 ? - function( elem, context, xml ) { - var i = matchers.length; - while ( i-- ) { - if ( !matchers[i]( elem, context, xml ) ) { - return false; - } - } - return true; - } : - matchers[0]; -} - -function multipleContexts( selector, contexts, results ) { - var i = 0, - len = contexts.length; - for ( ; i < len; i++ ) { - Sizzle( selector, contexts[i], results ); - } - return results; -} + "CHILD": function( match ) { -function condense( unmatched, map, filter, context, xml ) { - var elem, - newUnmatched = [], - i = 0, - len = unmatched.length, - mapped = map != null; + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); - for ( ; i < len; i++ ) { - if ( (elem = unmatched[i]) ) { - if ( !filter || filter( elem, context, xml ) ) { - newUnmatched.push( elem ); - if ( mapped ) { - map.push( i ); - } - } - } - } + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { - return newUnmatched; -} + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } -function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { - if ( postFilter && !postFilter[ expando ] ) { - postFilter = setMatcher( postFilter ); - } - if ( postFinder && !postFinder[ expando ] ) { - postFinder = setMatcher( postFinder, postSelector ); - } - return markFunction(function( seed, results, context, xml ) { - var temp, i, elem, - preMap = [], - postMap = [], - preexisting = results.length, + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); - // Get initial elements from seed or context - elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } - // Prefilter to get matcher input, preserving a map for seed-results synchronization - matcherIn = preFilter && ( seed || !selector ) ? - condense( elems, preMap, preFilter, context, xml ) : - elems, + return match; + }, - matcherOut = matcher ? - // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, - postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; - // ...intermediate processing is necessary - [] : + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } - // ...otherwise use results directly - results : - matcherIn; + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; - // Find primary matches - if ( matcher ) { - matcher( matcherIn, matcherOut, context, xml ); - } + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && - // Apply postFilter - if ( postFilter ) { - temp = condense( matcherOut, postMap ); - postFilter( temp, [], context, xml ); + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && - // Un-match failing elements by moving them back to matcherIn - i = temp.length; - while ( i-- ) { - if ( (elem = temp[i]) ) { - matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); - } - } - } + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { - if ( seed ) { - if ( postFinder || preFilter ) { - if ( postFinder ) { - // Get the final matcherOut by condensing this intermediate into postFinder contexts - temp = []; - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) ) { - // Restore matcherIn since elem is not yet a final match - temp.push( (matcherIn[i] = elem) ); + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); } - postFinder( null, (matcherOut = []), temp, xml ); - } + }, - // Move matched elements from seed to results to keep them synchronized - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) && - (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { + filter: { - seed[temp] = !(results[temp] = elem); - } - } - } + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } - // Add elements to results, through postFinder if defined - } else { - matcherOut = condense( - matcherOut === results ? - matcherOut.splice( preexisting, matcherOut.length ) : - matcherOut - ); - if ( postFinder ) { - postFinder( null, results, matcherOut, xml ); - } else { - push.apply( results, matcherOut ); - } - } - }); -} - -function matcherFromTokens( tokens ) { - var checkContext, matcher, j, - len = tokens.length, - leadingRelative = Expr.relative[ tokens[0].type ], - implicitRelative = leadingRelative || Expr.relative[" "], - i = leadingRelative ? 1 : 0, - - // The foundational matcher ensures that elements are reachable from top-level context(s) - matchContext = addCombinator( function( elem ) { - return elem === checkContext; - }, implicitRelative, true ), - matchAnyContext = addCombinator( function( elem ) { - return indexOf( checkContext, elem ) > -1; - }, implicitRelative, true ), - matchers = [ function( elem, context, xml ) { - var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( - (checkContext = context).nodeType ? - matchContext( elem, context, xml ) : - matchAnyContext( elem, context, xml ) ); - // Avoid hanging onto element (issue #299) - checkContext = null; - return ret; - } ]; + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } - for ( ; i < len; i++ ) { - if ( (matcher = Expr.relative[ tokens[i].type ]) ) { - matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; - } else { - matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); - - // Return special upon seeing a positional matcher - if ( matcher[ expando ] ) { - // Find the next relative operator (if any) for proper handling - j = ++i; - for ( ; j < len; j++ ) { - if ( Expr.relative[ tokens[j].type ] ) { - break; - } - } - return setMatcher( - i > 1 && elementMatcher( matchers ), - i > 1 && toSelector( - // If the preceding token was a descendant combinator, insert an implicit any-element `*` - tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) - ).replace( rtrim, "$1" ), - matcher, - i < j && matcherFromTokens( tokens.slice( i, j ) ), - j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), - j < len && toSelector( tokens ) - ); - } - matchers.push( matcher ); - } - } + start = [ forward ? parent.firstChild : parent.lastChild ]; - return elementMatcher( matchers ); -} - -function matcherFromGroupMatchers( elementMatchers, setMatchers ) { - var bySet = setMatchers.length > 0, - byElement = elementMatchers.length > 0, - superMatcher = function( seed, context, xml, results, outermost ) { - var elem, j, matcher, - matchedCount = 0, - i = "0", - unmatched = seed && [], - setMatched = [], - contextBackup = outermostContext, - // We must always have either seed elements or outermost context - elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), - // Use integer dirruns iff this is the outermost matcher - dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), - len = elems.length; - - if ( outermost ) { - outermostContext = context !== document && context; - } - - // Add elements passing elementMatchers directly to results - // Keep `i` a string if there are no elements so `matchedCount` will be "00" below - // Support: IE<9, Safari - // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id - for ( ; i !== len && (elem = elems[i]) != null; i++ ) { - if ( byElement && elem ) { - j = 0; - while ( (matcher = elementMatchers[j++]) ) { - if ( matcher( elem, context, xml ) ) { - results.push( elem ); - break; - } - } - if ( outermost ) { - dirruns = dirrunsUnique; - } - } + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { - // Track unmatched elements for set filters - if ( bySet ) { - // They will have gone through all possible matchers - if ( (elem = !matcher && elem) ) { - matchedCount--; - } + // Seek `elem` from a previously-cached index - // Lengthen the array for every element, matched or not - if ( seed ) { - unmatched.push( elem ); - } - } - } + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); - // Apply set filters to unmatched elements - matchedCount += i; - if ( bySet && i !== matchedCount ) { - j = 0; - while ( (matcher = setMatchers[j++]) ) { - matcher( unmatched, setMatched, context, xml ); - } + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); - if ( seed ) { - // Reintegrate element matches to eliminate the need for sorting - if ( matchedCount > 0 ) { - while ( i-- ) { - if ( !(unmatched[i] || setMatched[i]) ) { - setMatched[i] = pop.call( results ); - } - } - } + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; - // Discard index placeholder values to get only actual matches - setMatched = condense( setMatched ); - } + while ( ( node = ++nodeIndex && node && node[ dir ] || - // Add matches to results - push.apply( results, setMatched ); + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { - // Seedless set matches succeeding multiple successful matchers stipulate sorting - if ( outermost && !seed && setMatched.length > 0 && - ( matchedCount + setMatchers.length ) > 1 ) { + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } - Sizzle.uniqueSort( results ); - } - } + } else { - // Override manipulation of globals by nested matchers - if ( outermost ) { - dirruns = dirrunsUnique; - outermostContext = contextBackup; - } + // Use previously-cached element index if available + if ( useCache ) { - return unmatched; - }; + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); - return bySet ? - markFunction( superMatcher ) : - superMatcher; -} + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); -compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { - var i, - setMatchers = [], - elementMatchers = [], - cached = compilerCache[ selector + " " ]; + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } - if ( !cached ) { - // Generate a function of recursive functions that can be used to check each element - if ( !match ) { - match = tokenize( selector ); - } - i = match.length; - while ( i-- ) { - cached = matcherFromTokens( match[i] ); - if ( cached[ expando ] ) { - setMatchers.push( cached ); - } else { - elementMatchers.push( cached ); - } - } + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { - // Cache the compiled function - cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { - // Save selector and tokenization - cached.selector = selector; - } - return cached; -}; - -/** - * A low-level selection function that works with Sizzle's compiled - * selector functions - * @param {String|Function} selector A selector or a pre-compiled - * selector function built with Sizzle.compile - * @param {Element} context - * @param {Array} [results] - * @param {Array} [seed] A set of elements to match against - */ -select = Sizzle.select = function( selector, context, results, seed ) { - var i, tokens, token, type, find, - compiled = typeof selector === "function" && selector, - match = !seed && tokenize( (selector = compiled.selector || selector) ); + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { - results = results || []; + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); - // Try to minimize operations if there is no seed and only one group - if ( match.length === 1 ) { + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); - // Take a shortcut and set the context if the root selector is an ID - tokens = match[0] = match[0].slice( 0 ); - if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && - support.getById && context.nodeType === 9 && documentIsHTML && - Expr.relative[ tokens[1].type ] ) { + uniqueCache[ type ] = [ dirruns, diff ]; + } - context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; - if ( !context ) { - return results; + if ( node === elem ) { + break; + } + } + } + } + } - // Precompiled matchers will still verify ancestry, so step up a level - } else if ( compiled ) { - context = context.parentNode; - } + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } - selector = selector.slice( tokens.shift().value.length ); - } + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } - // Fetch a seed set for right-to-left matching - i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; - while ( i-- ) { - token = tokens[i]; - - // Abort if we hit a combinator - if ( Expr.relative[ (type = token.type) ] ) { - break; - } - if ( (find = Expr.find[ type ]) ) { - // Search, expanding context for leading sibling combinators - if ( (seed = find( - token.matches[0].replace( runescape, funescape ), - rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context - )) ) { - - // If seed is empty or no tokens remain, we can return early - tokens.splice( i, 1 ); - selector = seed.length && toSelector( tokens ); - if ( !selector ) { - push.apply( results, seed ); - return results; + return fn; } + }, - break; - } - } - } - } + pseudos: { - // Compile and execute a filtering function if one is not provided - // Provide `match` to avoid retokenization if we modified the selector above - ( compiled || compile( selector, match ) )( - seed, - context, - !documentIsHTML, - results, - rsibling.test( selector ) && testContext( context.parentNode ) || context - ); - return results; -}; + // Potentially complex pseudos + "not": markFunction( function( selector ) { -// One-time assignments + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); -// Sort stability -support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; -// Support: Chrome 14-35+ -// Always assume duplicates if they aren't passed to the comparison function -support.detectDuplicates = !!hasDuplicate; + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } -// Initialize against the default document -setDocument(); + return elem.selected === true; + }, -// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) -// Detached nodes confoundingly follow *each other* -support.sortDetached = assert(function( div1 ) { - // Should return 1, but returns 4 (following) - return div1.compareDocumentPosition( document.createElement("div") ) & 1; -}); + // Contents + "empty": function( elem ) { -// Support: IE<8 -// Prevent attribute/property "interpolation" -// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx -if ( !assert(function( div ) { - div.innerHTML = ""; - return div.firstChild.getAttribute("href") === "#" ; -}) ) { - addHandle( "type|href|height|width", function( elem, name, isXML ) { - if ( !isXML ) { - return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); - } - }); -} + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), -// Support: IE<9 -// Use defaultValue in place of getAttribute("value") -if ( !support.attributes || !assert(function( div ) { - div.innerHTML = ""; - div.firstChild.setAttribute( "value", "" ); - return div.firstChild.getAttribute( "value" ) === ""; -}) ) { - addHandle( "value", function( elem, name, isXML ) { - if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { - return elem.defaultValue; - } - }); -} + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), -// Support: IE<9 -// Use getAttributeNode to fetch booleans when getAttribute lies -if ( !assert(function( div ) { - return div.getAttribute("disabled") == null; -}) ) { - addHandle( booleans, function( elem, name, isXML ) { - var val; - if ( !isXML ) { - return elem[ name ] === true ? name.toLowerCase() : - (val = elem.getAttributeNode( name )) && val.specified ? - val.value : - null; - } - }); -} + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } + }; -return Sizzle; + Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; -})( window ); +// Add button/input type pseudos + for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); + } + for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); + } +// Easy API for creating new setFilters + function setFilters() {} + setFilters.prototype = Expr.filters = Expr.pseudos; + Expr.setFilters = new setFilters(); + tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; -jQuery.expr[":"] = jQuery.expr.pseudos; -jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + while ( soFar ) { -var rneedsContext = jQuery.expr.match.needsContext; + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { -var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/); + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + matched = false; + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, -var risSimple = /^.[^:#\[\.,]*$/; + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, not ) { - if ( jQuery.isFunction( qualifier ) ) { - return jQuery.grep( elements, function( elem, i ) { - /* jshint -W018 */ - return !!qualifier.call( elem, i, elem ) !== not; - }); + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } - } + if ( !matched ) { + break; + } + } - if ( qualifier.nodeType ) { - return jQuery.grep( elements, function( elem ) { - return ( elem === qualifier ) !== not; - }); + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : - } + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); + }; - if ( typeof qualifier === "string" ) { - if ( risSimple.test( qualifier ) ) { - return jQuery.filter( qualifier, elements, not ); - } + function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; + } - qualifier = jQuery.filter( qualifier, elements ); - } + function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; - return jQuery.grep( elements, function( elem ) { - return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not; - }); -} + return combinator.first ? -jQuery.filter = function( expr, elems, not ) { - var elem = elems[ 0 ]; + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; + } - if ( not ) { - expr = ":not(" + expr + ")"; - } + function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; + } - return elems.length === 1 && elem.nodeType === 1 ? - jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : - jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { - return elem.nodeType === 1; - })); -}; + function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; + } -jQuery.fn.extend({ - find: function( selector ) { - var i, - ret = [], - self = this, - len = self.length; + function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; - if ( typeof selector !== "string" ) { - return this.pushStack( jQuery( selector ).filter(function() { - for ( i = 0; i < len; i++ ) { - if ( jQuery.contains( self[ i ], this ) ) { - return true; + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } } } - }) ); - } - - for ( i = 0; i < len; i++ ) { - jQuery.find( selector, self[ i ], ret ); - } - // Needed because $( selector, context ) becomes $( context ).find( selector ) - ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); - ret.selector = this.selector ? this.selector + " " + selector : selector; - return ret; - }, - filter: function( selector ) { - return this.pushStack( winnow(this, selector || [], false) ); - }, - not: function( selector ) { - return this.pushStack( winnow(this, selector || [], true) ); - }, - is: function( selector ) { - return !!winnow( - this, - - // If this is a positional/relative selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - typeof selector === "string" && rneedsContext.test( selector ) ? - jQuery( selector ) : - selector || [], - false - ).length; - } -}); + return newUnmatched; + } + function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } -// Initialize a jQuery object + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } -// A central reference to the root jQuery(document) -var rootjQuery, + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { - // Use the correct document accordingly with window argument (sandbox) - document = window.document, + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { - // A simple way to check for HTML strings - // Prioritize #id over to avoid XSS via location.hash (#9521) - // Strict HTML recognition (#11290: must start with <) - rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } - init = jQuery.fn.init = function( selector, context ) { - var match, elem; + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { - // HANDLE: $(""), $(null), $(undefined), $(false) - if ( !selector ) { - return this; - } + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } - // Handle HTML strings - if ( typeof selector === "string" ) { - if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { - // Assume that strings that start and end with <> are HTML and skip the regex check - match = [ null, selector, null ]; + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); + } + + function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; - } else { - match = rquickExpr.exec( selector ); + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); } - // Match html or make sure no context is specified for #id - if ( match && (match[1] || !context) ) { + function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, - // HANDLE: $(html) -> $(array) - if ( match[1] ) { - context = context instanceof jQuery ? context[0] : context; + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), - // scripts is true for back-compat - // Intentionally let the error be thrown if parseHTML is not present - jQuery.merge( this, jQuery.parseHTML( - match[1], - context && context.nodeType ? context.ownerDocument || context : document, - true - ) ); + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; - // HANDLE: $(html, props) - if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { - for ( match in context ) { - // Properties of context are called as methods if possible - if ( jQuery.isFunction( this[ match ] ) ) { - this[ match ]( context[ match ] ); + if ( outermost ) { - // ...and otherwise set as attributes - } else { - this.attr( match, context[ match ] ); + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); } } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; + } + + compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } } - return this; + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); - // HANDLE: $(#id) - } else { - elem = document.getElementById( match[2] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id !== match[2] ) { - return rootjQuery.find( selector ); + // Save selector and tokenization + cached.selector = selector; + } + return cached; + }; + + /** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ + select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; } - // Otherwise, we inject the element directly into the jQuery object - this.length = 1; - this[0] = elem; + selector = selector.slice( tokens.shift().value.length ); } - this.context = document; - this.selector = selector; - return this; + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } } - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return ( context || rootjQuery ).find( selector ); + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; + }; - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); +// One-time assignments + +// Sort stability + support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function + support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document + setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* + support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; + } ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx + if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; + } ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); } - // HANDLE: $(DOMElement) - } else if ( selector.nodeType ) { - this.context = this[0] = selector; - this.length = 1; - return this; +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") + if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; + } ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); + } - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) { - return typeof rootjQuery.ready !== "undefined" ? - rootjQuery.ready( selector ) : - // Execute immediately if ready is not present - selector( jQuery ); - } +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies + if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; + } ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); + } - if ( selector.selector !== undefined ) { - this.selector = selector.selector; - this.context = selector.context; - } + return Sizzle; - return jQuery.makeArray( selector, this ); - }; + } )( window ); -// Give the init function the jQuery prototype for later instantiation -init.prototype = jQuery.fn; -// Initialize central reference -rootjQuery = jQuery( document ); + jQuery.find = Sizzle; + jQuery.expr = Sizzle.selectors; -var rparentsprev = /^(?:parents|prev(?:Until|All))/, - // methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; +// Deprecated + jQuery.expr[ ":" ] = jQuery.expr.pseudos; + jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; + jQuery.text = Sizzle.getText; + jQuery.isXMLDoc = Sizzle.isXML; + jQuery.contains = Sizzle.contains; + jQuery.escapeSelector = Sizzle.escape; -jQuery.extend({ - dir: function( elem, dir, until ) { + + + + var dir = function( elem, dir, until ) { var matched = [], - cur = elem[ dir ]; + truncate = until !== undefined; - while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { - if ( cur.nodeType === 1 ) { - matched.push( cur ); + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); } - cur = cur[dir]; } return matched; - }, + }; + - sibling: function( n, elem ) { - var r = []; + var siblings = function( n, elem ) { + var matched = []; for ( ; n; n = n.nextSibling ) { if ( n.nodeType === 1 && n !== elem ) { - r.push( n ); + matched.push( n ); } } - return r; - } -}); + return matched; + }; -jQuery.fn.extend({ - has: function( target ) { - var i, - targets = jQuery( target, this ), - len = targets.length; - return this.filter(function() { - for ( i = 0; i < len; i++ ) { - if ( jQuery.contains( this, targets[i] ) ) { - return true; - } - } - }); - }, + var rneedsContext = jQuery.expr.match.needsContext; - closest: function( selectors, context ) { - var cur, - i = 0, - l = this.length, - matched = [], - pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? - jQuery( selectors, context || this.context ) : - 0; - for ( ; i < l; i++ ) { - for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { - // Always skip document fragments - if ( cur.nodeType < 11 && (pos ? - pos.index(cur) > -1 : - // Don't pass non-elements to Sizzle - cur.nodeType === 1 && - jQuery.find.matchesSelector(cur, selectors)) ) { + function nodeName( elem, name ) { - matched.push( cur ); - break; - } - } - } + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); - return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched ); - }, + } + var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); - // Determine the position of an element within - // the matched set of elements - index: function( elem ) { - // No argument, return index in parent - if ( !elem ) { - return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; - } - // index in selector - if ( typeof elem === "string" ) { - return jQuery.inArray( this[0], jQuery( elem ) ); +// Implement the identical functionality for filter and not + function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); } - // Locate the position of the desired element - return jQuery.inArray( - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[0] : elem, this ); - }, + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } - add: function( selector, context ) { - return this.pushStack( - jQuery.unique( - jQuery.merge( this.get(), jQuery( selector, context ) ) - ) - ); - }, + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } - addBack: function( selector ) { - return this.add( selector == null ? - this.prevObject : this.prevObject.filter(selector) - ); - } -}); - -function sibling( cur, dir ) { - do { - cur = cur[ dir ]; - } while ( cur && cur.nodeType !== 1 ); - - return cur; -} - -jQuery.each({ - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return jQuery.dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, i, until ) { - return jQuery.dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return sibling( elem, "nextSibling" ); - }, - prev: function( elem ) { - return sibling( elem, "previousSibling" ); - }, - nextAll: function( elem ) { - return jQuery.dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return jQuery.dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, i, until ) { - return jQuery.dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, i, until ) { - return jQuery.dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); - }, - children: function( elem ) { - return jQuery.sibling( elem.firstChild ); - }, - contents: function( elem ) { - return jQuery.nodeName( elem, "iframe" ) ? - elem.contentDocument || elem.contentWindow.document : - jQuery.merge( [], elem.childNodes ); + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); } -}, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var ret = jQuery.map( this, fn, until ); - if ( name.slice( -5 ) !== "Until" ) { - selector = until; + jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; } - if ( selector && typeof selector === "string" ) { - ret = jQuery.filter( selector, ret ); + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; } - if ( this.length > 1 ) { - // Remove duplicates - if ( !guaranteedUnique[ name ] ) { - ret = jQuery.unique( ret ); + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); + }; + + jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); } - // Reverse order for parents* and prev-derivatives - if ( rparentsprev.test( name ) ) { - ret = ret.reverse(); + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; } + } ); - return this.pushStack( ret ); - }; -}); -var rnotwhite = (/\S+/g); +// Initialize a jQuery object -// String to Object options format cache -var optionsCache = {}; +// A central reference to the root jQuery(document) + var rootjQuery, -// Convert String-formatted options into Object-formatted ones and store in cache -function createOptions( options ) { - var object = optionsCache[ options ] = {}; - jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) { - object[ flag ] = true; - }); - return object; -} + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, -/* - * Create a callback list using the following parameters: - * - * options: an optional list of space-separated options that will change how - * the callback list behaves or a more traditional option object - * - * By default a callback list will act like an event callback list and can be - * "fired" multiple times. - * - * Possible options: - * - * once: will ensure the callback list can only be fired once (like a Deferred) - * - * memory: will keep track of previous values and will call any callback added - * after the list has been fired right away with the latest "memorized" - * values (like a Deferred) - * - * unique: will ensure a callback can only be added once (no duplicate in the list) - * - * stopOnFalse: interrupt callings when a callback returns false - * - */ -jQuery.Callbacks = function( options ) { - - // Convert options from String-formatted to Object-formatted if needed - // (we check in cache first) - options = typeof options === "string" ? - ( optionsCache[ options ] || createOptions( options ) ) : - jQuery.extend( {}, options ); - - var // Flag to know if list is currently firing - firing, - // Last fire value (for non-forgettable lists) - memory, - // Flag to know if list was already fired - fired, - // End of the loop when firing - firingLength, - // Index of currently firing callback (modified by remove if needed) - firingIndex, - // First callback to fire (used internally by add and fireWith) - firingStart, - // Actual callback list - list = [], - // Stack of fire calls for repeatable lists - stack = !options.once && [], - // Fire callbacks - fire = function( data ) { - memory = options.memory && data; - fired = true; - firingIndex = firingStart || 0; - firingStart = 0; - firingLength = list.length; - firing = true; - for ( ; list && firingIndex < firingLength; firingIndex++ ) { - if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { - memory = false; // To prevent further calls using add - break; - } + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; } - firing = false; - if ( list ) { - if ( stack ) { - if ( stack.length ) { - fire( stack.shift() ); - } - } else if ( memory ) { - list = []; + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + } else { - self.disable(); + match = rquickExpr.exec( selector ); } - } - }, - // Actual Callbacks object - self = { - // Add a callback or a collection of callbacks to the list - add: function() { - if ( list ) { - // First, we save the current length - var start = list.length; - (function add( args ) { - jQuery.each( args, function( _, arg ) { - var type = jQuery.type( arg ); - if ( type === "function" ) { - if ( !options.unique || !self.has( arg ) ) { - list.push( arg ); - } - } else if ( arg && arg.length && type !== "string" ) { - // Inspect recursively - add( arg ); - } - }); - })( arguments ); - // Do we need to add the callbacks to the - // current firing batch? - if ( firing ) { - firingLength = list.length; - // With memory, if we're not firing then - // we should call right away - } else if ( memory ) { - firingStart = start; - fire( memory ); - } - } - return this; - }, - // Remove a callback from the list - remove: function() { - if ( list ) { - jQuery.each( arguments, function( _, arg ) { - var index; - while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { - list.splice( index, 1 ); - // Handle firing indexes - if ( firing ) { - if ( index <= firingLength ) { - firingLength--; - } - if ( index <= firingIndex ) { - firingIndex--; + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); } } } - }); - } - return this; - }, - // Check if a given callback is in the list. - // If no argument is given, return whether or not list has callbacks attached. - has: function( fn ) { - return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); - }, - // Remove all callbacks from the list - empty: function() { - list = []; - firingLength = 0; - return this; - }, - // Have the list do nothing anymore - disable: function() { - list = stack = memory = undefined; - return this; - }, - // Is it disabled? - disabled: function() { - return !list; - }, - // Lock the list in its current state - lock: function() { - stack = undefined; - if ( !memory ) { - self.disable(); - } - return this; - }, - // Is it locked? - locked: function() { - return !stack; - }, - // Call all callbacks with the given context and arguments - fireWith: function( context, args ) { - if ( list && ( !fired || stack ) ) { - args = args || []; - args = [ context, args.slice ? args.slice() : args ]; - if ( firing ) { - stack.push( args ); + + return this; + + // HANDLE: $(#id) } else { - fire( args ); + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; return this; - }, - // Call all the callbacks with the given arguments - fire: function() { - self.fireWith( this, arguments ); - return this; - }, - // To know if the callbacks have already been called at least once - fired: function() { - return !!fired; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); } - }; - return self; -}; + return jQuery.makeArray( selector, this ); + }; +// Give the init function the jQuery prototype for later instantiation + init.prototype = jQuery.fn; -jQuery.extend({ +// Initialize central reference + rootjQuery = jQuery( document ); - Deferred: function( func ) { - var tuples = [ - // action, add listener, listener list, final state - [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], - [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], - [ "notify", "progress", jQuery.Callbacks("memory") ] - ], - state = "pending", - promise = { - state: function() { - return state; - }, - always: function() { - deferred.done( arguments ).fail( arguments ); - return this; - }, - then: function( /* fnDone, fnFail, fnProgress */ ) { - var fns = arguments; - return jQuery.Deferred(function( newDefer ) { - jQuery.each( tuples, function( i, tuple ) { - var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; - // deferred[ done | fail | progress ] for forwarding actions to newDefer - deferred[ tuple[1] ](function() { - var returned = fn && fn.apply( this, arguments ); - if ( returned && jQuery.isFunction( returned.promise ) ) { - returned.promise() - .done( newDefer.resolve ) - .fail( newDefer.reject ) - .progress( newDefer.notify ); - } else { - newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); - } - }); - }); - fns = null; - }).promise(); - }, - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - return obj != null ? jQuery.extend( obj, promise ) : promise; - } - }, - deferred = {}; - // Keep pipe for back-compat - promise.pipe = promise.then; + var rparentsprev = /^(?:parents|prev(?:Until|All))/, - // Add list-specific methods - jQuery.each( tuples, function( i, tuple ) { - var list = tuple[ 2 ], - stateString = tuple[ 3 ]; + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; - // promise[ done | fail | progress ] = list.add - promise[ tuple[1] ] = list.add; + jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; - // Handle state - if ( stateString ) { - list.add(function() { - // state = [ resolved | rejected ] - state = stateString; + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, - // [ reject_list | resolve_list ].disable; progress_list.lock - }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); - } + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); - // deferred[ resolve | reject | notify ] - deferred[ tuple[0] ] = function() { - deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); - return this; - }; - deferred[ tuple[0] + "With" ] = list.fireWith; - }); + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { - // Make the deferred a promise - promise.promise( deferred ); + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { - // All done! - return deferred; - }, + matched.push( cur ); + break; + } + } + } + } - // Deferred helper - when: function( subordinate /* , ..., subordinateN */ ) { - var i = 0, - resolveValues = slice.call( arguments ), - length = resolveValues.length, + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, - // the count of uncompleted subordinates - remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + // Determine the position of an element within the set + index: function( elem ) { - // the master Deferred. If resolveValues consist of only a single Deferred, just use that. - deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } - // Update function for both resolve and progress values - updateFunc = function( i, contexts, values ) { - return function( value ) { - contexts[ i ] = this; - values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; - if ( values === progressValues ) { - deferred.notifyWith( contexts, values ); + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } - } else if ( !(--remaining) ) { - deferred.resolveWith( contexts, values ); - } - }; - }, + // Locate the position of the desired element + return indexOf.call( this, - progressValues, progressContexts, resolveContexts; + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, - // add listeners to Deferred subordinates; treat others as resolved - if ( length > 1 ) { - progressValues = new Array( length ); - progressContexts = new Array( length ); - resolveContexts = new Array( length ); - for ( ; i < length; i++ ) { - if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { - resolveValues[ i ].promise() - .done( updateFunc( i, resolveContexts, resolveValues ) ) - .fail( deferred.reject ) - .progress( updateFunc( i, progressContexts, progressValues ) ); - } else { - --remaining; - } - } - } + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, - // if we're not waiting on anything, resolve the master - if ( !remaining ) { - deferred.resolveWith( resolveContexts, resolveValues ); + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); } + } ); - return deferred.promise(); + function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; } -}); - - -// The deferred used on DOM ready -var readyList; -jQuery.fn.ready = function( fn ) { - // Add the callback - jQuery.ready.promise().done( fn ); + jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && - return this; -}; + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { -jQuery.extend({ - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, + return elem.contentDocument; + } - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } - // Hold (or release) the ready event - holdReady: function( hold ) { - if ( hold ) { - jQuery.readyWait++; - } else { - jQuery.ready( true ); + return jQuery.merge( [], elem.childNodes ); } - }, + }, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); - // Handle when the DOM is ready - ready: function( wait ) { + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } - // Abort if there are pending holds or we're already ready - if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { - return; - } + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). - if ( !document.body ) { - return setTimeout( jQuery.ready ); - } + if ( this.length > 1 ) { - // Remember that the DOM is ready - jQuery.isReady = true; + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } - // If there are functions bound, to execute - readyList.resolveWith( document, [ jQuery ] ); + return this.pushStack( matched ); + }; + } ); + var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); - // Trigger any bound ready events - if ( jQuery.fn.triggerHandler ) { - jQuery( document ).triggerHandler( "ready" ); - jQuery( document ).off( "ready" ); - } - } -}); -/** - * Clean-up method for dom ready events - */ -function detach() { - if ( document.addEventListener ) { - document.removeEventListener( "DOMContentLoaded", completed, false ); - window.removeEventListener( "load", completed, false ); - } else { - document.detachEvent( "onreadystatechange", completed ); - window.detachEvent( "onload", completed ); +// Convert String-formatted options into Object-formatted ones + function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; } -} -/** - * The ready event handler and self cleanup method + /* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * */ -function completed() { - // readyState === "complete" is good enough for us to call the dom ready in oldIE - if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { - detach(); - jQuery.ready(); - } -} + jQuery.Callbacks = function( options ) { -jQuery.ready.promise = function( obj ) { - if ( !readyList ) { + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); - readyList = jQuery.Deferred(); + var // Flag to know if list is currently firing + firing, - // Catch cases where $(document).ready() is called after the browser event has already occurred. - // we once tried to use readyState "interactive" here, but it caused issues like the one - // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 - if ( document.readyState === "complete" ) { - // Handle it asynchronously to allow scripts the opportunity to delay ready - setTimeout( jQuery.ready ); + // Last fire value for non-forgettable lists + memory, - // Standards-based browsers support DOMContentLoaded - } else if ( document.addEventListener ) { - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", completed, false ); + // Flag to know if list was already fired + fired, - // A fallback to window.onload, that will always work - window.addEventListener( "load", completed, false ); + // Flag to prevent firing + locked, - // If IE event model is used - } else { - // Ensure firing before onload, maybe late but safe also for iframes - document.attachEvent( "onreadystatechange", completed ); + // Actual callback list + list = [], - // A fallback to window.onload, that will always work - window.attachEvent( "onload", completed ); + // Queue of execution data for repeatable lists + queue = [], - // If IE and not a frame - // continually check to see if the document is ready - var top = false; + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, - try { - top = window.frameElement == null && document.documentElement; - } catch(e) {} - - if ( top && top.doScroll ) { - (function doScrollCheck() { - if ( !jQuery.isReady ) { - - try { - // Use the trick by Diego Perini - // http://javascript.nwbox.com/IEContentLoaded/ - top.doScroll("left"); - } catch(e) { - return setTimeout( doScrollCheck, 50 ); - } + // Fire callbacks + fire = function() { - // detach all dom ready events - detach(); + // Enforce single-firing + locked = locked || options.once; - // and execute any waiting functions - jQuery.ready(); - } - })(); - } - } - } - return readyList.promise( obj ); -}; + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } -var strundefined = typeof undefined; + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + firing = false; + // Clean up if we're done firing for good + if ( locked ) { -// Support: IE<9 -// Iteration over object's inherited properties before its own -var i; -for ( i in jQuery( support ) ) { - break; -} -support.ownLast = i !== "0"; - -// Note: most support tests are defined in their respective modules. -// false until the test is run -support.inlineBlockNeedsLayout = false; - -// Execute ASAP in case we need to set body.style.zoom -jQuery(function() { - // Minified: var a,b,c,d - var val, div, body, container; - - body = document.getElementsByTagName( "body" )[ 0 ]; - if ( !body || !body.style ) { - // Return for frameset docs that don't have a body - return; - } + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; - // Setup - div = document.createElement( "div" ); - container = document.createElement( "div" ); - container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px"; - body.appendChild( container ).appendChild( div ); - - if ( typeof div.style.zoom !== strundefined ) { - // Support: IE<8 - // Check if natively block-level elements act like inline-block - // elements when setting their display to 'inline' and giving - // them layout - div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1"; - - support.inlineBlockNeedsLayout = val = div.offsetWidth === 3; - if ( val ) { - // Prevent IE 6 from affecting layout for positioned elements #11048 - // Prevent IE from shrinking the body in IE 7 mode #12869 - // Support: IE<8 - body.style.zoom = 1; - } - } + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, - body.removeChild( container ); -}); + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { -(function() { - var div = document.createElement( "div" ); + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); - // Execute the test only if not already executed in another module. - if (support.deleteExpando == null) { - // Support: IE<9 - support.deleteExpando = true; - try { - delete div.test; - } catch( e ) { - support.deleteExpando = false; - } - } + if ( memory && !firing ) { + fire(); + } + } + return this; + }, - // Null elements to avoid leaks in IE. - div = null; -})(); + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, -/** - * Determines whether an object can have data - */ -jQuery.acceptData = function( elem ) { - var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ], - nodeType = +elem.nodeType || 1; + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, - // Do not set data on non-element DOM nodes because it will not be cleared (#8335). - return nodeType !== 1 && nodeType !== 9 ? - false : + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, - // Nodes accept data unless otherwise specified; rejection can be conditional - !noData || noData !== true && elem.getAttribute("classid") === noData; -}; + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, -var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, - rmultiDash = /([A-Z])/g; + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, -function dataAttr( elem, key, data ) { - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, - var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; - data = elem.getAttribute( name ); + return self; + }; - if ( typeof data === "string" ) { - try { - data = data === "true" ? true : - data === "false" ? false : - data === "null" ? null : - // Only convert to a number if it doesn't change the string - +data + "" === data ? +data : - rbrace.test( data ) ? jQuery.parseJSON( data ) : - data; - } catch( e ) {} - - // Make sure we set the data so it isn't changed later - jQuery.data( elem, key, data ); - } else { - data = undefined; - } + function Identity( v ) { + return v; + } + function Thrower( ex ) { + throw ex; } - return data; -} - -// checks a cache object for emptiness -function isEmptyDataObject( obj ) { - var name; - for ( name in obj ) { + function adoptValue( value, resolve, reject, noValue ) { + var method; - // if the public data object is empty, the private is still empty - if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { - continue; - } - if ( name !== "toJSON" ) { - return false; - } - } + try { - return true; -} + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); -function internalData( elem, name, data, pvt /* Internal Use Only */ ) { - if ( !jQuery.acceptData( elem ) ) { - return; - } + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); - var ret, thisCache, - internalKey = jQuery.expando, + // Other non-thenables + } else { - // We have to handle DOM nodes and JS objects differently because IE6-7 - // can't GC object references properly across the DOM-JS boundary - isNode = elem.nodeType, + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } + } + + jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { - // Only DOM nodes need the global jQuery cache; JS object data is - // attached directly to the object so GC can occur automatically - cache = isNode ? jQuery.cache : elem, + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } - // Only defining an ID for JS objects if its cache already exists allows - // the code to shortcut on the same path as a DOM node with no cache - id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; - // Avoid doing any more work than we need to when trying to get data on an - // object that has no data at all - if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) { - return; - } + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; - if ( !id ) { - // Only DOM nodes need a new unique ID for each element since their data - // ends up in the global cache - if ( isNode ) { - id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++; - } else { - id = internalKey; - } - } + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; - if ( !cache[ id ] ) { - // Avoid exposing jQuery metadata on plain JS objects when the object - // is serialized using JSON.stringify - cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; - } + // Handle state + if ( stateString ) { + list.add( + function() { - // An object can be passed to jQuery.data instead of a key/value pair; this gets - // shallow copied over onto the existing cache - if ( typeof name === "object" || typeof name === "function" ) { - if ( pvt ) { - cache[ id ] = jQuery.extend( cache[ id ], name ); - } else { - cache[ id ].data = jQuery.extend( cache[ id ].data, name ); - } - } + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, - thisCache = cache[ id ]; + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, - // jQuery data() is stored in a separate object inside the object's internal data - // cache in order to avoid key collisions between internal data and user-defined - // data. - if ( !pvt ) { - if ( !thisCache.data ) { - thisCache.data = {}; - } + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, - thisCache = thisCache.data; - } + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, - if ( data !== undefined ) { - thisCache[ jQuery.camelCase( name ) ] = data; - } + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } - // Check for both converted-to-camel and non-converted data property names - // If a data property was specified - if ( typeof name === "string" ) { + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); - // First Try to find as-is property data - ret = thisCache[ name ]; + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; - // Test for null|undefined property data - if ( ret == null ) { + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); - // Try to find the camelCased property - ret = thisCache[ jQuery.camelCase( name ) ]; - } - } else { - ret = thisCache; - } + // Make the deferred a promise + promise.promise( deferred ); - return ret; -} + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } -function internalRemoveData( elem, name, pvt ) { - if ( !jQuery.acceptData( elem ) ) { - return; - } + // All done! + return deferred; + }, - var thisCache, i, - isNode = elem.nodeType, + // Deferred helper + when: function( singleValue ) { + var - // See jQuery.data for more information - cache = isNode ? jQuery.cache : elem, - id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + // count of uncompleted subordinates + remaining = arguments.length, - // If there is already no cache entry for this object, there is no - // purpose in continuing - if ( !cache[ id ] ) { - return; - } + // count of unprocessed arguments + i = remaining, - if ( name ) { + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), - thisCache = pvt ? cache[ id ] : cache[ id ].data; + // the primary Deferred + primary = jQuery.Deferred(), - if ( thisCache ) { + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + primary.resolveWith( resolveContexts, resolveValues ); + } + }; + }; - // Support array or space separated string names for data keys - if ( !jQuery.isArray( name ) ) { + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject, + !remaining ); - // try the string as a key before any manipulation - if ( name in thisCache ) { - name = [ name ]; - } else { + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( primary.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { - // split the camel cased version by spaces unless a key with the spaces exists - name = jQuery.camelCase( name ); - if ( name in thisCache ) { - name = [ name ]; - } else { - name = name.split(" "); - } + return primary.then(); } - } else { - // If "name" is an array of keys... - // When data is initially created, via ("key", "val") signature, - // keys will be converted to camelCase. - // Since there is no way to tell _how_ a key was added, remove - // both plain key and camelCase key. #12786 - // This will only penalize the array argument path. - name = name.concat( jQuery.map( name, jQuery.camelCase ) ); } - i = name.length; + // Multiple arguments are aggregated like Promise.all array elements while ( i-- ) { - delete thisCache[ name[i] ]; + adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject ); } - // If there is no data left in the cache, we want to continue - // and let the cache object itself get destroyed - if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) { - return; - } + return primary.promise(); } - } + } ); - // See jQuery.data for more information - if ( !pvt ) { - delete cache[ id ].data; - // Don't destroy the parent cache unless the internal data object - // had been the only thing left in it - if ( !isEmptyDataObject( cache[ id ] ) ) { - return; - } - } +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. + var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; - // Destroy the cache - if ( isNode ) { - jQuery.cleanData( [ elem ], true ); + jQuery.Deferred.exceptionHook = function( error, stack ) { - // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) - /* jshint eqeqeq: false */ - } else if ( support.deleteExpando || cache != cache.window ) { - /* jshint eqeqeq: true */ - delete cache[ id ]; + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } + }; - // When all else fails, null - } else { - cache[ id ] = null; - } -} - -jQuery.extend({ - cache: {}, - - // The following elements (space-suffixed to avoid Object.prototype collisions) - // throw uncatchable exceptions if you attempt to set expando properties - noData: { - "applet ": true, - "embed ": true, - // ...but Flash objects (which have this classid) *can* handle expandos - "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" - }, - - hasData: function( elem ) { - elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; - return !!elem && !isEmptyDataObject( elem ); - }, - - data: function( elem, name, data ) { - return internalData( elem, name, data ); - }, - - removeData: function( elem, name ) { - return internalRemoveData( elem, name ); - }, - - // For internal use only. - _data: function( elem, name, data ) { - return internalData( elem, name, data, true ); - }, - - _removeData: function( elem, name ) { - return internalRemoveData( elem, name, true ); - } -}); -jQuery.fn.extend({ - data: function( key, value ) { - var i, name, data, - elem = this[0], - attrs = elem && elem.attributes; - // Special expections of .data basically thwart jQuery.access, - // so implement the relevant behavior ourselves - // Gets all values - if ( key === undefined ) { - if ( this.length ) { - data = jQuery.data( elem ); + jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); + }; - if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { - i = attrs.length; - while ( i-- ) { - // Support: IE11+ - // The attrs elements can be null (#14894) - if ( attrs[ i ] ) { - name = attrs[ i ].name; - if ( name.indexOf( "data-" ) === 0 ) { - name = jQuery.camelCase( name.slice(5) ); - dataAttr( elem, name, data[ name ] ); - } - } - } - jQuery._data( elem, "parsedAttrs", true ); - } - } - return data; - } - // Sets multiple values - if ( typeof key === "object" ) { - return this.each(function() { - jQuery.data( this, key ); - }); - } +// The deferred used on DOM ready + var readyList = jQuery.Deferred(); - return arguments.length > 1 ? + jQuery.fn.ready = function( fn ) { - // Sets one value - this.each(function() { - jQuery.data( this, key, value ); - }) : - - // Gets one value - // Try to fetch any internally stored data first - elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined; - }, - - removeData: function( key ) { - return this.each(function() { - jQuery.removeData( this, key ); - }); - } -}); + readyList + .then( fn ) + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); -jQuery.extend({ - queue: function( elem, type, data ) { - var queue; + return this; + }; - if ( elem ) { - type = ( type || "fx" ) + "queue"; - queue = jQuery._data( elem, type ); + jQuery.extend( { - // Speed up dequeue by getting out quickly if this is just a lookup - if ( data ) { - if ( !queue || jQuery.isArray(data) ) { - queue = jQuery._data( elem, type, jQuery.makeArray(data) ); - } else { - queue.push( data ); - } - } - return queue || []; - } - }, + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, - dequeue: function( elem, type ) { - type = type || "fx"; + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, - var queue = jQuery.queue( elem, type ), - startLength = queue.length, - fn = queue.shift(), - hooks = jQuery._queueHooks( elem, type ), - next = function() { - jQuery.dequeue( elem, type ); - }; + // Handle when the DOM is ready + ready: function( wait ) { - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - startLength--; - } + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } - if ( fn ) { + // Remember that the DOM is ready + jQuery.isReady = true; - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift( "inprogress" ); + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; } - // clear up the last queue stop function - delete hooks.stop; - fn.call( elem, next, hooks ); + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); } + } ); - if ( !startLength && hooks ) { - hooks.empty.fire(); - } - }, + jQuery.ready.then = readyList.then; - // not intended for public consumption - generates a queueHooks object, or returns the current one - _queueHooks: function( elem, type ) { - var key = type + "queueHooks"; - return jQuery._data( elem, key ) || jQuery._data( elem, key, { - empty: jQuery.Callbacks("once memory").add(function() { - jQuery._removeData( elem, type + "queue" ); - jQuery._removeData( elem, key ); - }) - }); +// The ready event handler and self cleanup method + function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); } -}); - -jQuery.fn.extend({ - queue: function( type, data ) { - var setter = 2; - - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - setter--; - } - if ( arguments.length < setter ) { - return jQuery.queue( this[0], type ); - } - - return data === undefined ? - this : - this.each(function() { - var queue = jQuery.queue( this, type, data ); +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon + if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { - // ensure a hooks for this queue - jQuery._queueHooks( this, type ); + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); - if ( type === "fx" && queue[0] !== "inprogress" ) { - jQuery.dequeue( this, type ); - } - }); - }, - dequeue: function( type ) { - return this.each(function() { - jQuery.dequeue( this, type ); - }); - }, - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - }, - // Get a promise resolved when queues of a certain type - // are emptied (fx is the type by default) - promise: function( type, obj ) { - var tmp, - count = 1, - defer = jQuery.Deferred(), - elements = this, - i = this.length, - resolve = function() { - if ( !( --count ) ) { - defer.resolveWith( elements, [ elements ] ); - } - }; + } else { - if ( typeof type !== "string" ) { - obj = type; - type = undefined; - } - type = type || "fx"; + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); - while ( i-- ) { - tmp = jQuery._data( elements[ i ], type + "queueHooks" ); - if ( tmp && tmp.empty ) { - count++; - tmp.empty.add( resolve ); - } - } - resolve(); - return defer.promise( obj ); + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); } -}); -var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source; -var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; - -var isHidden = function( elem, el ) { - // isHidden might be called from jQuery#filter function; - // in that case, element will be second argument - elem = el || elem; - return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); - }; // Multifunctional method to get and set values of a collection // The value/s can optionally be executed if it's a function -var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) { - var i = 0, - length = elems.length, - bulk = key == null; + var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; - // Sets many values - if ( jQuery.type( key ) === "object" ) { - chainable = true; - for ( i in key ) { - jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); - } + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; - // Sets one value - } else if ( value !== undefined ) { - chainable = true; + if ( !isFunction( value ) ) { + raw = true; + } - if ( !jQuery.isFunction( value ) ) { - raw = true; - } + if ( bulk ) { - if ( bulk ) { - // Bulk operations run against the entire set - if ( raw ) { - fn.call( elems, value ); - fn = null; + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; - // ...except when executing function values - } else { - bulk = fn; - fn = function( elem, key, value ) { - return bulk.call( jQuery( elem ), value ); - }; + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } } - } - if ( fn ) { - for ( ; i < length; i++ ) { - fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } } } - } - return chainable ? - elems : + if ( chainable ) { + return elems; + } // Gets - bulk ? - fn.call( elems ) : - length ? fn( elems[0], key ) : emptyGet; -}; -var rcheckableType = (/^(?:checkbox|radio)$/i); - - - -(function() { - // Minified: var a,b,c - var input = document.createElement( "input" ), - div = document.createElement( "div" ), - fragment = document.createDocumentFragment(); - - // Setup - div.innerHTML = "
a"; - - // IE strips leading whitespace when .innerHTML is used - support.leadingWhitespace = div.firstChild.nodeType === 3; - - // Make sure that tbody elements aren't automatically inserted - // IE will insert them into empty tables - support.tbody = !div.getElementsByTagName( "tbody" ).length; - - // Make sure that link elements get serialized correctly by innerHTML - // This requires a wrapper element in IE - support.htmlSerialize = !!div.getElementsByTagName( "link" ).length; - - // Makes sure cloning an html5 element does not cause problems - // Where outerHTML is undefined, this still works - support.html5Clone = - document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav>"; - - // Check if a disconnected checkbox will retain its checked - // value of true after appended to the DOM (IE6/7) - input.type = "checkbox"; - input.checked = true; - fragment.appendChild( input ); - support.appendChecked = input.checked; - - // Make sure textarea (and checkbox) defaultValue is properly cloned - // Support: IE6-IE11+ - div.innerHTML = ""; - support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; - - // #11217 - WebKit loses check when the name is after the checked attribute - fragment.appendChild( div ); - div.innerHTML = ""; - - // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3 - // old WebKit doesn't clone checked state correctly in fragments - support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; - - // Support: IE<9 - // Opera does not clone events (and typeof div.attachEvent === undefined). - // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() - support.noCloneEvent = true; - if ( div.attachEvent ) { - div.attachEvent( "onclick", function() { - support.noCloneEvent = false; - }); - - div.cloneNode( true ).click(); - } - - // Execute the test only if not already executed in another module. - if (support.deleteExpando == null) { - // Support: IE<9 - support.deleteExpando = true; - try { - delete div.test; - } catch( e ) { - support.deleteExpando = false; + if ( bulk ) { + return fn.call( elems ); } - } -})(); + return len ? fn( elems[ 0 ], key ) : emptyGet; + }; -(function() { - var i, eventName, - div = document.createElement( "div" ); - // Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event) - for ( i in { submit: true, change: true, focusin: true }) { - eventName = "on" + i; +// Matches dashed string for camelizing + var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; - if ( !(support[ i + "Bubbles" ] = eventName in window) ) { - // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) - div.setAttribute( eventName, "t" ); - support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false; - } +// Used by camelCase as callback to replace() + function fcamelCase( _all, letter ) { + return letter.toUpperCase(); } - // Null elements to avoid leaks in IE. - div = null; -})(); +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) + function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + } + var acceptData = function( owner ) { + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); + }; -var rformElems = /^(?:input|select|textarea)$/i, - rkeyEvent = /^key/, - rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/, - rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, - rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; -function returnTrue() { - return true; -} -function returnFalse() { - return false; -} -function safeActiveElement() { - try { - return document.activeElement; - } catch ( err ) { } -} + function Data() { + this.expando = jQuery.expando + Data.uid++; + } -/* - * Helper functions for managing events -- not part of the public interface. - * Props to Dean Edwards' addEvent library for many of the ideas. - */ -jQuery.event = { + Data.uid = 1; - global: {}, + Data.prototype = { - add: function( elem, types, handler, data, selector ) { - var tmp, events, t, handleObjIn, - special, eventHandle, handleObj, - handlers, type, namespaces, origType, - elemData = jQuery._data( elem ); + cache: function( owner ) { - // Don't attach events to noData or text/comment nodes (but allow plain objects) - if ( !elemData ) { - return; - } + // Check if the owner object already has a cache + var value = owner[ this.expando ]; - // Caller can pass in an object of custom data in lieu of the handler - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - selector = handleObjIn.selector; - } + // If not, create one + if ( !value ) { + value = {}; - // Make sure that the handler has a unique ID, used to find/remove it later - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { - // Init the element's event structure and main handler, if this is the first - if ( !(events = elemData.events) ) { - events = elemData.events = {}; - } - if ( !(eventHandle = elemData.handle) ) { - eventHandle = elemData.handle = function( e ) { - // Discard the second event of a jQuery.event.trigger() and - // when an event is called after a page has unloaded - return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ? - jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : - undefined; - }; - // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events - eventHandle.elem = elem; - } + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); - // Handle multiple events separated by a space - types = ( types || "" ).match( rnotwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[t] ) || []; - type = origType = tmp[1]; - namespaces = ( tmp[2] || "" ).split( "." ).sort(); + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; - // There *must* be a type, no attaching namespace-only handlers - if ( !type ) { - continue; + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : - // If event changes its type, use the special event handlers for the changed type - special = jQuery.event.special[ type ] || {}; + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; - // If selector defined, determine special event api type, otherwise given type - type = ( selector ? special.delegateType : special.bindType ) || type; + if ( cache === undefined ) { + return; + } - // Update special based on newly reset type - special = jQuery.event.special[ type ] || {}; + if ( key !== undefined ) { - // handleObj is passed to all event handlers - handleObj = jQuery.extend({ - type: type, - origType: origType, - data: data, - handler: handler, - guid: handler.guid, - selector: selector, - needsContext: selector && jQuery.expr.match.needsContext.test( selector ), - namespace: namespaces.join(".") - }, handleObjIn ); + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { - // Init the event handler queue if we're the first - if ( !(handlers = events[ type ]) ) { - handlers = events[ type ] = []; - handlers.delegateCount = 0; + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); - // Only use addEventListener/attachEvent if the special events handler returns false - if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - // Bind the global event handler to the element - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle, false ); + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } - } else if ( elem.attachEvent ) { - elem.attachEvent( "on" + type, eventHandle ); - } + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; } } - if ( special.add ) { - special.add.call( elem, handleObj ); + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; } } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } + }; + var dataPriv = new Data(); + + var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + + var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + + function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; + } + + function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); - // Add to the element's handler list, delegates in front - if ( selector ) { - handlers.splice( handlers.delegateCount++, 0, handleObj ); + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); } else { - handlers.push( handleObj ); + data = undefined; } - - // Keep track of which events have ever been used, for event optimization - jQuery.event.global[ type ] = true; } + return data; + } - // Nullify elem to prevent memory leaks in IE - elem = null; - }, + jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, - // Detach an event or set of events from an element - remove: function( elem, types, handler, selector, mappedTypes ) { - var j, handleObj, tmp, - origCount, t, events, - special, handlers, type, - namespaces, origType, - elemData = jQuery.hasData( elem ) && jQuery._data( elem ); + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, - if ( !elemData || !(events = elemData.events) ) { - return; - } + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, - // Once for each type.namespace in types; type may be omitted - types = ( types || "" ).match( rnotwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[t] ) || []; - type = origType = tmp[1]; - namespaces = ( tmp[2] || "" ).split( "." ).sort(); + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, - // Unbind all events (on this namespace, if provided) for the element - if ( !type ) { - for ( type in events ) { - jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); - } - continue; - } + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } + } ); - special = jQuery.event.special[ type ] || {}; - type = ( selector ? special.delegateType : special.bindType ) || type; - handlers = events[ type ] || []; - tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); + jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; - // Remove matching events - origCount = j = handlers.length; - while ( j-- ) { - handleObj = handlers[ j ]; + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); - if ( ( mappedTypes || origType === handleObj.origType ) && - ( !handler || handler.guid === handleObj.guid ) && - ( !tmp || tmp.test( handleObj.namespace ) ) && - ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { - handlers.splice( j, 1 ); + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { - if ( handleObj.selector ) { - handlers.delegateCount--; - } - if ( special.remove ) { - special.remove.call( elem, handleObj ); + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); } } - } - - // Remove generic event handler if we removed something and no more handlers exist - // (avoids potential for endless recursion during removal of special event handlers) - if ( origCount && !handlers.length ) { - if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { - jQuery.removeEvent( elem, type, elemData.handle ); - } - delete events[ type ]; + return data; } - } - - // Remove the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - delete elemData.handle; - // removeData also checks for emptiness and clears the expando if empty - // so use it instead of delete - jQuery._removeData( elem, "events" ); - } - }, + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } - trigger: function( event, data, elem, onlyHandlers ) { - var handle, ontype, cur, - bubbleType, special, tmp, i, - eventPath = [ elem || document ], - type = hasOwn.call( event, "type" ) ? event.type : event, - namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; + return access( this, function( value ) { + var data; - cur = tmp = elem = elem || document; + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { - // Don't do events on text and comment nodes - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } - // focus/blur morphs to focusin/out; ensure we're not firing them right now - if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { - return; - } + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } - if ( type.indexOf(".") >= 0 ) { - // Namespaced trigger; create a regexp to match event type in handle() - namespaces = type.split("."); - type = namespaces.shift(); - namespaces.sort(); - } - ontype = type.indexOf(":") < 0 && "on" + type; + // We tried really hard, but the data doesn't exist. + return; + } - // Caller can pass in a jQuery.Event object, Object, or just an event type string - event = event[ jQuery.expando ] ? - event : - new jQuery.Event( type, typeof event === "object" && event ); + // Set the data... + this.each( function() { - // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) - event.isTrigger = onlyHandlers ? 2 : 3; - event.namespace = namespaces.join("."); - event.namespace_re = event.namespace ? - new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : - null; + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, - // Clean up the event in case it is being reused - event.result = undefined; - if ( !event.target ) { - event.target = elem; + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); } + } ); - // Clone any incoming data and prepend the event, creating the handler arg list - data = data == null ? - [ event ] : - jQuery.makeArray( data, [ event ] ); - // Allow special events to draw outside the lines - special = jQuery.event.special[ type ] || {}; - if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { - return; - } + jQuery.extend( { + queue: function( elem, type, data ) { + var queue; - // Determine event propagation path in advance, per W3C events spec (#9951) - // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) - if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); - bubbleType = special.delegateType || type; - if ( !rfocusMorph.test( bubbleType + type ) ) { - cur = cur.parentNode; - } - for ( ; cur; cur = cur.parentNode ) { - eventPath.push( cur ); - tmp = cur; + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; - // Only add window if we got to document (e.g., not plain obj or detached DOM) - if ( tmp === (elem.ownerDocument || document) ) { - eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; } - } - // Fire handlers on the event path - i = 0; - while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { + if ( fn ) { - event.type = i > 1 ? - bubbleType : - special.bindType || type; + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } - // jQuery handler - handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); - if ( handle ) { - handle.apply( cur, data ); + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); } - // Native handler - handle = ontype && cur[ ontype ]; - if ( handle && handle.apply && jQuery.acceptData( cur ) ) { - event.result = handle.apply( cur, data ); - if ( event.result === false ) { - event.preventDefault(); - } + if ( !startLength && hooks ) { + hooks.empty.fire(); } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); } - event.type = type; + } ); - // If nobody prevented the default action, do it now - if ( !onlyHandlers && !event.isDefaultPrevented() ) { + jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; - if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && - jQuery.acceptData( elem ) ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } - // Call a native DOM method on the target with the same name name as the event. - // Can't use an .isFunction() check here because IE6/7 fails that test. - // Don't do default actions on window, that's where global variables be (#6170) - if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } - // Don't re-trigger an onFOO event when we call its FOO() method - tmp = elem[ ontype ]; + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); - if ( tmp ) { - elem[ ontype ] = null; - } + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); - // Prevent re-triggering of the same event, since we already bubbled it above - jQuery.event.triggered = type; - try { - elem[ type ](); - } catch ( e ) { - // IE<9 dies on focus/blur to hidden element (#1486,#12518) - // only reproducible on winXP IE8 native, not IE9 in IE8 mode + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); } - jQuery.event.triggered = undefined; + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, - if ( tmp ) { - elem[ ontype ] = tmp; + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); } } + resolve(); + return defer.promise( obj ); } + } ); + var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; - return event.result; - }, + var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); - dispatch: function( event ) { - // Make a writable jQuery.Event from the native event object - event = jQuery.event.fix( event ); + var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; - var i, ret, handleObj, matched, j, - handlerQueue = [], - args = slice.call( arguments ), - handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], - special = jQuery.event.special[ event.type ] || {}; + var documentElement = document.documentElement; - // Use the fix-ed jQuery.Event rather than the (read-only) native event - args[0] = event; - event.delegateTarget = this; - // Call the preDispatch hook for the mapped type, and let it bail if desired - if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { - return; - } - // Determine handlers - handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } + var isHiddenWithinTree = function( elem, el ) { - // Run delegates first; they may want to stop propagation beneath us - i = 0; - while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { - event.currentTarget = matched.elem; + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; - j = 0; - while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && - // Triggered event must either 1) have no namespace, or - // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). - if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && - event.handleObj = handleObj; - event.data = handleObj.data; + jQuery.css( elem, "display" ) === "none"; + }; - ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) - .apply( matched.elem, args ); - if ( ret !== undefined ) { - if ( (event.result = ret) === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } - } - // Call the postDispatch hook for the mapped type - if ( special.postDispatch ) { - special.postDispatch.call( this, event ); - } + function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), - return event.result; - }, + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); - handlers: function( event, handlers ) { - var sel, handleObj, matches, i, - handlerQueue = [], - delegateCount = handlers.delegateCount, - cur = event.target; + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { - // Find delegate handlers - // Black-hole SVG instance trees (#13180) - // Avoid non-left-click bubbling in Firefox (#3861) - if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; - /* jshint eqeqeq: false */ - for ( ; cur != this; cur = cur.parentNode || this ) { - /* jshint eqeqeq: true */ + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; - // Don't check non-elements (#13208) - // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) - if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) { - matches = []; - for ( i = 0; i < delegateCount; i++ ) { - handleObj = handlers[ i ]; + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; - // Don't conflict with Object.prototype properties (#13203) - sel = handleObj.selector + " "; + while ( maxIterations-- ) { - if ( matches[ sel ] === undefined ) { - matches[ sel ] = handleObj.needsContext ? - jQuery( sel, this ).index( cur ) >= 0 : - jQuery.find( sel, this, null, [ cur ] ).length; - } - if ( matches[ sel ] ) { - matches.push( handleObj ); - } - } - if ( matches.length ) { - handlerQueue.push({ elem: cur, handlers: matches }); - } + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; } - } - } + initialInUnit = initialInUnit / scale; - // Add the remaining (directly-bound) handlers - if ( delegateCount < handlers.length ) { - handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); - } + } - return handlerQueue; - }, + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); - fix: function( event ) { - if ( event[ jQuery.expando ] ) { - return event; + // Make sure we update the tween properties later on + valueParts = valueParts || []; } - // Create a writable copy of the event object and normalize some properties - var i, prop, copy, - type = event.type, - originalEvent = event, - fixHook = this.fixHooks[ type ]; + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; - if ( !fixHook ) { - this.fixHooks[ type ] = fixHook = - rmouseEvent.test( type ) ? this.mouseHooks : - rkeyEvent.test( type ) ? this.keyHooks : - {}; + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } } - copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + return adjusted; + } - event = new jQuery.Event( originalEvent ); - i = copy.length; - while ( i-- ) { - prop = copy[ i ]; - event[ prop ] = originalEvent[ prop ]; - } + var defaultDisplayMap = {}; - // Support: IE<9 - // Fix target property (#1925) - if ( !event.target ) { - event.target = originalEvent.srcElement || document; - } + function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; - // Support: Chrome 23+, Safari? - // Target should not be a text node (#504, #13143) - if ( event.target.nodeType === 3 ) { - event.target = event.target.parentNode; + if ( display ) { + return display; } - // Support: IE<9 - // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) - event.metaKey = !!event.metaKey; - - return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; - }, - - // Includes some event props shared by KeyEvent and MouseEvent - props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), - - fixHooks: {}, - - keyHooks: { - props: "char charCode key keyCode".split(" "), - filter: function( event, original ) { + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); - // Add which for key events - if ( event.which == null ) { - event.which = original.charCode != null ? original.charCode : original.keyCode; - } + temp.parentNode.removeChild( temp ); - return event; + if ( display === "none" ) { + display = "block"; } - }, - - mouseHooks: { - props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), - filter: function( event, original ) { - var body, eventDoc, doc, - button = original.button, - fromElement = original.fromElement; + defaultDisplayMap[ nodeName ] = display; - // Calculate pageX/Y if missing and clientX/Y available - if ( event.pageX == null && original.clientX != null ) { - eventDoc = event.target.ownerDocument || document; - doc = eventDoc.documentElement; - body = eventDoc.body; - - event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); - event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); - } + return display; + } - // Add relatedTarget, if necessary - if ( !event.relatedTarget && fromElement ) { - event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; - } + function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; - // Add which for click: 1 === left; 2 === middle; 3 === right - // Note: button is not normalized, so don't use it - if ( !event.which && button !== undefined ) { - event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; } - return event; - } - }, + display = elem.style.display; + if ( show ) { - special: { - load: { - // Prevent triggered image.load events from bubbling to window.load - noBubble: true - }, - focus: { - // Fire native event if possible so blur/focus sequence is correct - trigger: function() { - if ( this !== safeActiveElement() && this.focus ) { - try { - this.focus(); - return false; - } catch ( e ) { - // Support: IE<9 - // If we error on focus to hidden element (#1486, #12518), - // let .trigger() run the handlers + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; } } - }, - delegateType: "focusin" - }, - blur: { - trigger: function() { - if ( this === safeActiveElement() && this.blur ) { - this.blur(); - return false; - } - }, - delegateType: "focusout" - }, - click: { - // For checkbox, fire native event so checked state will be right - trigger: function() { - if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { - this.click(); - return false; + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); } - }, - - // For cross-browser consistency, don't fire native .click() on links - _default: function( event ) { - return jQuery.nodeName( event.target, "a" ); - } - }, - - beforeunload: { - postDispatch: function( event ) { + } else { + if ( display !== "none" ) { + values[ index ] = "none"; - // Support: Firefox 20+ - // Firefox doesn't alert if the returnValue field is not set. - if ( event.result !== undefined && event.originalEvent ) { - event.originalEvent.returnValue = event.result; + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); } } } - }, - simulate: function( type, elem, event, bubble ) { - // Piggyback on a donor event to simulate a different one. - // Fake originalEvent to avoid donor's stopPropagation, but if the - // simulated event prevents default then we do the same on the donor. - var e = jQuery.extend( - new jQuery.Event(), - event, - { - type: type, - isSimulated: true, - originalEvent: {} + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; } - ); - if ( bubble ) { - jQuery.event.trigger( e, null, elem ); - } else { - jQuery.event.dispatch.call( elem, e ); - } - if ( e.isDefaultPrevented() ) { - event.preventDefault(); } + + return elements; } -}; -jQuery.removeEvent = document.removeEventListener ? - function( elem, type, handle ) { - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle, false ); + jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); } - } : - function( elem, type, handle ) { - var name = "on" + type; + } ); + var rcheckableType = ( /^(?:checkbox|radio)$/i ); - if ( elem.detachEvent ) { + var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); - // #8545, #7054, preventing memory leaks for custom events in IE6-8 - // detachEvent needed property on element, by name of that event, to properly expose it to GC - if ( typeof elem[ name ] === strundefined ) { - elem[ name ] = null; - } + var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); - elem.detachEvent( name, handle ); - } - }; -jQuery.Event = function( src, props ) { - // Allow instantiation without the 'new' keyword - if ( !(this instanceof jQuery.Event) ) { - return new jQuery.Event( src, props ); - } - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = src.defaultPrevented || - src.defaultPrevented === undefined && - // Support: IE < 9, Android < 4.0 - src.returnValue === false ? - returnTrue : - returnFalse; - - // Event type - } else { - this.type = src; - } + ( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); - // Put explicitly provided properties onto the event object - if ( props ) { - jQuery.extend( this, props ); - } + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); - // Create a timestamp if incoming event doesn't have one - this.timeStamp = src && src.timeStamp || jQuery.now(); + div.appendChild( input ); - // Mark it as fixed - this[ jQuery.expando ] = true; -}; + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; -// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -jQuery.Event.prototype = { - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse, + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; - preventDefault: function() { - var e = this.originalEvent; + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; + } )(); - this.isDefaultPrevented = returnTrue; - if ( !e ) { - return; - } - // If preventDefault exists, run it on the original event - if ( e.preventDefault ) { - e.preventDefault(); +// We have to close these tags to support XHTML (#13200) + var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] + }; + + wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; + wrapMap.th = wrapMap.td; + +// Support: IE <=9 only + if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; + } + + + function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); - // Support: IE - // Otherwise set the returnValue property of the original event to false } else { - e.returnValue = false; + ret = []; } - }, - stopPropagation: function() { - var e = this.originalEvent; - this.isPropagationStopped = returnTrue; - if ( !e ) { - return; - } - // If stopPropagation exists, run it on the original event - if ( e.stopPropagation ) { - e.stopPropagation(); + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); } - // Support: IE - // Set the cancelBubble property of the original event to true - e.cancelBubble = true; - }, - stopImmediatePropagation: function() { - var e = this.originalEvent; + return ret; + } + - this.isImmediatePropagationStopped = returnTrue; +// Mark scripts as having already been evaluated + function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; - if ( e && e.stopImmediatePropagation ) { - e.stopImmediatePropagation(); + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); } - - this.stopPropagation(); } -}; -// Create mouseenter/leave events using mouseover/out and event-time checks -jQuery.each({ - mouseenter: "mouseover", - mouseleave: "mouseout", - pointerenter: "pointerover", - pointerleave: "pointerout" -}, function( orig, fix ) { - jQuery.event.special[ orig ] = { - delegateType: fix, - bindType: fix, - - handle: function( event ) { - var ret, - target = this, - related = event.relatedTarget, - handleObj = event.handleObj; - - // For mousenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if ( !related || (related !== target && !jQuery.contains( target, related )) ) { - event.type = handleObj.origType; - ret = handleObj.handler.apply( this, arguments ); - event.type = fix; - } - return ret; - } - }; -}); -// IE submit delegation -if ( !support.submitBubbles ) { + var rhtml = /<|&#?\w+;/; - jQuery.event.special.submit = { - setup: function() { - // Only need this for delegated form submit events - if ( jQuery.nodeName( this, "form" ) ) { - return false; - } + function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; - // Lazy-add a submit handler when a descendant form may potentially be submitted - jQuery.event.add( this, "click._submit keypress._submit", function( e ) { - // Node name check avoids a VML-related crash in IE (#9807) - var elem = e.target, - form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; - if ( form && !jQuery._data( form, "submitBubbles" ) ) { - jQuery.event.add( form, "submit._submit", function( event ) { - event._submit_bubble = true; - }); - jQuery._data( form, "submitBubbles", true ); - } - }); - // return undefined since we don't need an event listener - }, + for ( ; i < l; i++ ) { + elem = elems[ i ]; - postDispatch: function( event ) { - // If form was submitted by the user, bubble the event up the tree - if ( event._submit_bubble ) { - delete event._submit_bubble; - if ( this.parentNode && !event.isTrigger ) { - jQuery.event.simulate( "submit", this.parentNode, event, true ); - } - } - }, + if ( elem || elem === 0 ) { - teardown: function() { - // Only need this for delegated form submit events - if ( jQuery.nodeName( this, "form" ) ) { - return false; - } + // Add nodes directly + if ( toType( elem ) === "object" ) { - // Remove delegated handlers; cleanData eventually reaps submit handlers attached above - jQuery.event.remove( this, "._submit" ); - } - }; -} + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); -// IE change delegation and checkbox/radio fix -if ( !support.changeBubbles ) { + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); - jQuery.event.special.change = { + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); - setup: function() { + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; - if ( rformElems.test( this.nodeName ) ) { - // IE doesn't fire change on a check/radio until blur; trigger it on click - // after a propertychange. Eat the blur-change in special.change.handle. - // This still fires onchange a second time for check/radio after blur. - if ( this.type === "checkbox" || this.type === "radio" ) { - jQuery.event.add( this, "propertychange._change", function( event ) { - if ( event.originalEvent.propertyName === "checked" ) { - this._just_changed = true; - } - }); - jQuery.event.add( this, "click._change", function( event ) { - if ( this._just_changed && !event.isTrigger ) { - this._just_changed = false; - } - // Allow triggered, simulated change events (#11500) - jQuery.event.simulate( "change", this, event, true ); - }); + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; } - return false; } - // Delegated event; lazy-add a change handler on descendant inputs - jQuery.event.add( this, "beforeactivate._change", function( e ) { - var elem = e.target; + } - if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) { - jQuery.event.add( elem, "change._change", function( event ) { - if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { - jQuery.event.simulate( "change", this.parentNode, event, true ); - } - }); - jQuery._data( elem, "changeBubbles", true ); - } - }); - }, + // Remove wrapper from fragment + fragment.textContent = ""; - handle: function( event ) { - var elem = event.target; + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { - // Swallow native change events from checkbox/radio, we already triggered them above - if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { - return event.handleObj.handler.apply( this, arguments ); + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; } - }, - teardown: function() { - jQuery.event.remove( this, "._change" ); + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } - return !rformElems.test( this.nodeName ); + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } } - }; -} -// Create "bubbling" focus and blur events -if ( !support.focusinBubbles ) { - jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + return fragment; + } + - // Attach a single capturing handler on the document while someone wants focusin/focusout - var handler = function( event ) { - jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); - }; + var rtypenamespace = /^([^.]*)(?:\.(.+)|)/; - jQuery.event.special[ fix ] = { - setup: function() { - var doc = this.ownerDocument || this, - attaches = jQuery._data( doc, fix ); + function returnTrue() { + return true; + } - if ( !attaches ) { - doc.addEventListener( orig, handler, true ); - } - jQuery._data( doc, fix, ( attaches || 0 ) + 1 ); - }, - teardown: function() { - var doc = this.ownerDocument || this, - attaches = jQuery._data( doc, fix ) - 1; + function returnFalse() { + return false; + } - if ( !attaches ) { - doc.removeEventListener( orig, handler, true ); - jQuery._removeData( doc, fix ); - } else { - jQuery._data( doc, fix, attaches ); - } - } - }; - }); -} +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). + function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); + } -jQuery.fn.extend({ +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 + function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } + } - on: function( types, selector, data, fn, /*INTERNAL*/ one ) { - var type, origFn; + function on( elem, types, selector, data, fn, one ) { + var origFn, type; // Types can be a map of types/handlers if ( typeof types === "object" ) { + // ( types-Object, selector, data ) if ( typeof selector !== "string" ) { + // ( types-Object, data ) data = data || selector; selector = undefined; } for ( type in types ) { - this.on( type, selector, data, types[ type ], one ); + on( elem, type, selector, data, types[ type ], one ); } - return this; + return elem; } if ( data == null && fn == null ) { + // ( types, fn ) fn = selector; data = selector = undefined; } else if ( fn == null ) { if ( typeof selector === "string" ) { + // ( types, selector, fn ) fn = data; data = undefined; } else { + // ( types, data, fn ) fn = data; data = selector; @@ -5232,722 +5163,913 @@ jQuery.fn.extend({ if ( fn === false ) { fn = returnFalse; } else if ( !fn ) { - return this; + return elem; } if ( one === 1 ) { origFn = fn; fn = function( event ) { + // Can use an empty set, since event contains the info jQuery().off( event ); return origFn.apply( this, arguments ); }; + // Use same guid so caller can remove using origFn fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); } - return this.each( function() { + return elem.each( function() { jQuery.event.add( this, types, fn, data, selector ); - }); - }, - one: function( types, selector, data, fn ) { - return this.on( types, selector, data, fn, 1 ); - }, - off: function( types, selector, fn ) { - var handleObj, type; - if ( types && types.preventDefault && types.handleObj ) { - // ( event ) dispatched jQuery.Event - handleObj = types.handleObj; - jQuery( types.delegateTarget ).off( - handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, - handleObj.selector, - handleObj.handler - ); - return this; - } - if ( typeof types === "object" ) { - // ( types-object [, selector] ) - for ( type in types ) { - this.off( type, selector, types[ type ] ); - } - return this; - } - if ( selector === false || typeof selector === "function" ) { - // ( types [, fn] ) - fn = selector; - selector = undefined; - } - if ( fn === false ) { - fn = returnFalse; - } - return this.each(function() { - jQuery.event.remove( this, types, fn, selector ); - }); - }, - - trigger: function( type, data ) { - return this.each(function() { - jQuery.event.trigger( type, data, this ); - }); - }, - triggerHandler: function( type, data ) { - var elem = this[0]; - if ( elem ) { - return jQuery.event.trigger( type, data, elem, true ); - } + } ); } -}); + /* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ + jQuery.event = { + + global: {}, -function createSafeFragment( document ) { - var list = nodeNames.split( "|" ), - safeFrag = document.createDocumentFragment(); + add: function( elem, types, handler, data, selector ) { - if ( safeFrag.createElement ) { - while ( list.length ) { - safeFrag.createElement( - list.pop() - ); - } - } - return safeFrag; -} - -var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + - "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", - rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, - rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), - rleadingWhitespace = /^\s+/, - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, - rtagName = /<([\w:]+)/, - rtbody = /\s*$/g, - - // We have to close these tags to support XHTML (#13200) - wrapMap = { - option: [ 1, "" ], - legend: [ 1, "
", "
" ], - area: [ 1, "", "" ], - param: [ 1, "", "" ], - thead: [ 1, "", "
" ], - tr: [ 2, "", "
" ], - col: [ 2, "", "
" ], - td: [ 3, "", "
" ], + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); - // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, - // unless wrapped in a div with non-breaking characters in front of it. - _default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
", "
" ] - }, - safeFragment = createSafeFragment( document ), - fragmentDiv = safeFragment.appendChild( document.createElement("div") ); - -wrapMap.optgroup = wrapMap.option; -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - -function getAll( context, tag ) { - var elems, elem, - i = 0, - found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || "*" ) : - typeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || "*" ) : - undefined; - - if ( !found ) { - for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { - if ( !tag || jQuery.nodeName( elem, tag ) ) { - found.push( elem ); - } else { - jQuery.merge( found, getAll( elem, tag ) ); + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; } - } - } - return tag === undefined || tag && jQuery.nodeName( context, tag ) ? - jQuery.merge( [ context ], found ) : - found; -} + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } -// Used in buildFragment, fixes the defaultChecked property -function fixDefaultChecked( elem ) { - if ( rcheckableType.test( elem.type ) ) { - elem.defaultChecked = elem.checked; - } -} + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } -// Support: IE<8 -// Manipulating tables requires a tbody -function manipulationTarget( elem, content ) { - return jQuery.nodeName( elem, "table" ) && - jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ? + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } - elem.getElementsByTagName("tbody")[0] || - elem.appendChild( elem.ownerDocument.createElement("tbody") ) : - elem; -} + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { -// Replace/restore the type attribute of script elements for safe DOM manipulation -function disableScript( elem ) { - elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type; - return elem; -} -function restoreScript( elem ) { - var match = rscriptTypeMasked.exec( elem.type ); - if ( match ) { - elem.type = match[1]; - } else { - elem.removeAttribute("type"); - } - return elem; -} + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } -// Mark scripts as having already been evaluated -function setGlobalEval( elems, refElements ) { - var elem, - i = 0; - for ( ; (elem = elems[i]) != null; i++ ) { - jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); - } -} + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); -function cloneCopyEvent( src, dest ) { + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } - if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { - return; - } + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; - var type, i, l, - oldData = jQuery._data( src ), - curData = jQuery._data( dest, oldData ), - events = oldData.events; + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; - if ( events ) { - delete curData.handle; - curData.events = {}; + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; - for ( type in events ) { - for ( i = 0, l = events[ type ].length; i < l; i++ ) { - jQuery.event.add( dest, type, events[ type ][ i ] ); - } - } - } + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } - // make the cloned public data object a copy from the original - if ( curData.data ) { - curData.data = jQuery.extend( {}, curData.data ); - } -} + if ( special.add ) { + special.add.call( elem, handleObj ); -function fixCloneNodeIssues( src, dest ) { - var nodeName, e, data; + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } - // We do not need to do anything for non-Elements - if ( dest.nodeType !== 1 ) { - return; - } + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } - nodeName = dest.nodeName.toLowerCase(); + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } - // IE6-8 copies events bound via attachEvent when using cloneNode. - if ( !support.noCloneEvent && dest[ jQuery.expando ] ) { - data = jQuery._data( dest ); + }, - for ( e in data.events ) { - jQuery.removeEvent( dest, e, data.handle ); - } + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { - // Event data gets referenced instead of copied if the expando gets copied too - dest.removeAttribute( jQuery.expando ); - } + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); - // IE blanks contents when cloning scripts, and tries to evaluate newly-set text - if ( nodeName === "script" && dest.text !== src.text ) { - disableScript( dest ).text = src.text; - restoreScript( dest ); + if ( !elemData || !( events = elemData.events ) ) { + return; + } - // IE6-10 improperly clones children of object elements using classid. - // IE10 throws NoModificationAllowedError if parent is null, #12132. - } else if ( nodeName === "object" ) { - if ( dest.parentNode ) { - dest.outerHTML = src.outerHTML; - } + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); - // This path appears unavoidable for IE9. When cloning an object - // element in IE9, the outerHTML strategy above is not sufficient. - // If the src has innerHTML and the destination does not, - // copy the src.innerHTML into the dest.innerHTML. #10324 - if ( support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { - dest.innerHTML = src.innerHTML; - } + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } - } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) { - // IE6-8 fails to persist the checked state of a cloned checkbox - // or radio button. Worse, IE6-7 fail to give the cloned element - // a checked appearance if the defaultChecked value isn't also set + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } - dest.defaultChecked = dest.checked = src.checked; + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { - // IE6-7 get confused and end up setting the value of a cloned - // checkbox/radio button to an empty string instead of "on" - if ( dest.value !== src.value ) { - dest.value = src.value; - } + jQuery.removeEvent( elem, type, elemData.handle ); + } - // IE6-8 fails to return the selected option to the default selected - // state when cloning options - } else if ( nodeName === "option" ) { - dest.defaultSelected = dest.selected = src.defaultSelected; + delete events[ type ]; + } + } - // IE6-8 fails to set the defaultValue to the correct value when - // cloning other types of input fields - } else if ( nodeName === "input" || nodeName === "textarea" ) { - dest.defaultValue = src.defaultValue; - } -} + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, -jQuery.extend({ - clone: function( elem, dataAndEvents, deepDataAndEvents ) { - var destElements, node, clone, i, srcElements, - inPage = jQuery.contains( elem.ownerDocument, elem ); + dispatch: function( nativeEvent ) { - if ( support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { - clone = elem.cloneNode( true ); + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), - // IE<=8 does not properly clone detached, unknown element nodes - } else { - fragmentDiv.innerHTML = elem.outerHTML; - fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); - } + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), - if ( (!support.noCloneEvent || !support.noCloneChecked) && - (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; - // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 - destElements = getAll( clone ); - srcElements = getAll( elem ); + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; - // Fix all IE cloning issues - for ( i = 0; (node = srcElements[i]) != null; ++i ) { - // Ensure that the destination node is not null; Fixes #9587 - if ( destElements[i] ) { - fixCloneNodeIssues( node, destElements[i] ); - } + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; } - } - // Copy the events from the original to the clone - if ( dataAndEvents ) { - if ( deepDataAndEvents ) { - srcElements = srcElements || getAll( elem ); - destElements = destElements || getAll( clone ); + event.delegateTarget = this; - for ( i = 0; (node = srcElements[i]) != null; i++ ) { - cloneCopyEvent( node, destElements[i] ); - } - } else { - cloneCopyEvent( elem, clone ); + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; } - } - // Preserve script evaluation history - destElements = getAll( clone, "script" ); - if ( destElements.length > 0 ) { - setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); - } + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); - destElements = srcElements = node = null; + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; - // Return the cloned set - return clone; - }, + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { - buildFragment: function( elems, context, scripts, selection ) { - var j, elem, contains, - tmp, tag, tbody, wrap, - l = elems.length, + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { - // Ensure a safe fragment - safe = createSafeFragment( context ), + event.handleObj = handleObj; + event.data = handleObj.data; - nodes = [], - i = 0; + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); - for ( ; i < l; i++ ) { - elem = elems[ i ]; + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } - if ( elem || elem === 0 ) { + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } - // Add nodes directly - if ( jQuery.type( elem ) === "object" ) { - jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + return event.result; + }, - // Convert non-html into a text node - } else if ( !rhtml.test( elem ) ) { - nodes.push( context.createTextNode( elem ) ); + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } - // Convert html into DOM nodes - } else { - tmp = tmp || safe.appendChild( context.createElement("div") ); + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } - // Deserialize a standard representation - tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase(); - wrap = wrapMap[ tag ] || wrapMap._default; + return handlerQueue; + }, - tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[2]; + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, - // Descend through wrappers to the right content - j = wrap[0]; - while ( j-- ) { - tmp = tmp.lastChild; - } + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, - // Manually add leading whitespace removed by IE - if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { - nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); - } + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, - // Remove IE's autoinserted from table fragments - if ( !support.tbody ) { + special: { + load: { - // String was a , *may* have spurious - elem = tag === "table" && !rtbody.test( elem ) ? - tmp.firstChild : + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { - // String was a bare or - wrap[1] === "
" && !rtbody.test( elem ) ? - tmp : - 0; + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { - j = elem && elem.childNodes.length; - while ( j-- ) { - if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { - elem.removeChild( tbody ); - } - } + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); } - jQuery.merge( nodes, tmp.childNodes ); + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { - // Fix #12392 for WebKit and IE > 9 - tmp.textContent = ""; + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { - // Fix #12392 for oldIE - while ( tmp.firstChild ) { - tmp.removeChild( tmp.firstChild ); + leverageNative( el, "click" ); } - // Remember the top-level container for proper cleanup - tmp = safe.lastChild; + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); } - } - } + }, - // Fix #11356: Clear elements from fragment - if ( tmp ) { - safe.removeChild( tmp ); - } + beforeunload: { + postDispatch: function( event ) { - // Reset defaultChecked for any radios and checkboxes - // about to be appended to the DOM in IE 6/7 (#8060) - if ( !support.appendChecked ) { - jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } } + }; - i = 0; - while ( (elem = nodes[ i++ ]) ) { +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. + function leverageNative( el, type, expectSync ) { - // #4087 - If origin and destination elements are the same, and this is - // that element, do not do anything - if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { - continue; + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); } + return; + } - contains = jQuery.contains( elem.ownerDocument, elem ); + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { - // Append to fragment - tmp = getAll( safe.appendChild( elem ), "script" ); + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); - // Preserve script evaluation history - if ( contains ) { - setGlobalEval( tmp ); - } + // Support: Chrome 86+ + // In Chrome, if an element having a focusout handler is blurred by + // clicking outside of it, it invokes the handler synchronously. If + // that handler calls `.remove()` on the element, the data is cleared, + // leaving `result` undefined. We need to guard against this. + return result && result.value; + } - // Capture executables - if ( scripts ) { - j = 0; - while ( (elem = tmp[ j++ ]) ) { - if ( rscriptType.test( elem.type || "" ) ) { - scripts.push( elem ); + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); } } + } ); + } + + jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); } + }; - tmp = null; + jQuery.Event = function( src, props ) { - return safe; - }, + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } - cleanData: function( elems, /* internal */ acceptData ) { - var elem, type, id, data, - i = 0, - internalKey = jQuery.expando, - cache = jQuery.cache, - deleteExpando = support.deleteExpando, - special = jQuery.event.special; + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; - for ( ; (elem = elems[i]) != null; i++ ) { - if ( acceptData || jQuery.acceptData( elem ) ) { + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && - id = elem[ internalKey ]; - data = id && cache[ id ]; + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; - if ( data ) { - if ( data.events ) { - for ( type in data.events ) { - if ( special[ type ] ) { - jQuery.event.remove( elem, type ); + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; - // This is a shortcut to avoid jQuery.event.remove's overhead - } else { - jQuery.removeEvent( elem, type, data.handle ); - } - } - } + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; - // Remove cache only if it was not already removed by jQuery.event.remove - if ( cache[ id ] ) { + // Event type + } else { + this.type = src; + } - delete cache[ id ]; + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } - // IE does not allow us to delete expando properties from nodes, - // nor does it have a removeAttribute function on Document nodes; - // we must handle all of these cases - if ( deleteExpando ) { - delete elem[ internalKey ]; + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); - } else if ( typeof elem.removeAttribute !== strundefined ) { - elem.removeAttribute( internalKey ); + // Mark it as fixed + this[ jQuery.expando ] = true; + }; - } else { - elem[ internalKey ] = null; - } +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html + jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, - deletedIds.push( id ); - } - } + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); } - } - } -}); - -jQuery.fn.extend({ - text: function( value ) { - return access( this, function( value ) { - return value === undefined ? - jQuery.text( this ) : - this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); - }, null, value, arguments.length ); - }, - - append: function() { - return this.domManip( arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.appendChild( elem ); - } - }); - }, - - prepend: function() { - return this.domManip( arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.insertBefore( elem, target.firstChild ); - } - }); - }, - - before: function() { - return this.domManip( arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this ); - } - }); - }, - - after: function() { - return this.domManip( arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this.nextSibling ); - } - }); - }, - - remove: function( selector, keepData /* Internal Use Only */ ) { - var elem, - elems = selector ? jQuery.filter( selector, this ) : this, - i = 0; + }, + stopPropagation: function() { + var e = this.originalEvent; - for ( ; (elem = elems[i]) != null; i++ ) { + this.isPropagationStopped = returnTrue; - if ( !keepData && elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem ) ); + if ( e && !this.isSimulated ) { + e.stopPropagation(); } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; - if ( elem.parentNode ) { - if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { - setGlobalEval( getAll( elem, "script" ) ); - } - elem.parentNode.removeChild( elem ); + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); } + + this.stopPropagation(); } + }; - return this; - }, +// Includes all common event props including KeyEvent and MouseEvent specific props + jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + which: true + }, jQuery.event.addProp ); + + jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { - empty: function() { - var elem, - i = 0; + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); - for ( ; (elem = this[i]) != null; i++ ) { - // Remove element nodes and prevent memory leaks - if ( elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem, false ) ); + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + // Suppress native focus or blur as it's already being fired + // in leverageNative. + _default: function() { + return true; + }, + + delegateType: delegateType + }; + } ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). + jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" + }, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; + } ); + + jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; } + if ( typeof types === "object" ) { - // Remove any remaining nodes - while ( elem.firstChild ) { - elem.removeChild( elem.firstChild ); + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; } + if ( selector === false || typeof selector === "function" ) { - // If this is a select, ensure that it displays empty (#12336) - // Support: IE<9 - if ( elem.options && jQuery.nodeName( elem, "select" ) ) { - elem.options.length = 0; + // ( types [, fn] ) + fn = selector; + selector = undefined; } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); } + } ); - return this; - }, - - clone: function( dataAndEvents, deepDataAndEvents ) { - dataAndEvents = dataAndEvents == null ? false : dataAndEvents; - deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; - return this.map(function() { - return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); - }); - }, + var - html: function( value ) { - return access( this, function( value ) { - var elem = this[ 0 ] || {}, - i = 0, - l = this.length; + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; - // See if we can take a shortcut and just use innerHTML - if ( typeof value === "string" && !rnoInnerhtml.test( value ) && - ( support.htmlSerialize || !rnoshimcache.test( value ) ) && - ( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && - !wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) { +// Prefer a tbody over its parent table for containing new rows + function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { - value = value.replace( rxhtmlTag, "<$1>" ); + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } - try { - for (; i < l; i++ ) { - // Remove element nodes and prevent memory leaks - elem = this[i] || {}; - if ( elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem, false ) ); - elem.innerHTML = value; - } - } + return elem; + } - elem = 0; +// Replace/restore the type attribute of script elements for safe DOM manipulation + function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; + } + function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } - // If using innerHTML throws an exception, use the fallback method - } catch(e) {} - } + return elem; + } - if ( elem ) { - this.empty().append( value ); - } - }, null, value, arguments.length ); - }, + function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; - replaceWith: function() { - var arg = arguments[ 0 ]; + if ( dest.nodeType !== 1 ) { + return; + } - // Make the changes, replacing each context element with the new content - this.domManip( arguments, function( elem ) { - arg = this.parentNode; + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; - jQuery.cleanData( getAll( this ) ); + if ( events ) { + dataPriv.remove( dest, "handle events" ); - if ( arg ) { - arg.replaceChild( elem, this ); + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } } - }); + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } + } - // Force removal if there was no new content (e.g., from empty arguments) - return arg && (arg.length || arg.nodeType) ? this : this.remove(); - }, +// Fix IE bugs, see support tests + function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); - detach: function( selector ) { - return this.remove( selector, true ); - }, + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; - domManip: function( args, callback ) { + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } + } + + function domManip( collection, args, callback, ignored ) { // Flatten any nested arrays - args = concat.apply( [], args ); + args = flat( args ); - var first, node, hasScripts, - scripts, doc, fragment, + var fragment, first, scripts, hasScripts, node, doc, i = 0, - l = this.length, - set = this, + l = collection.length, iNoClone = l - 1, - value = args[0], - isFunction = jQuery.isFunction( value ); + value = args[ 0 ], + valueIsFunction = isFunction( value ); // We can't cloneNode fragments that contain checked, in WebKit - if ( isFunction || - ( l > 1 && typeof value === "string" && - !support.checkClone && rchecked.test( value ) ) ) { - return this.each(function( index ) { - var self = set.eq( index ); - if ( isFunction ) { - args[0] = value.call( this, index, self.html() ); + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); } - self.domManip( args, callback ); - }); + domManip( self, args, callback, ignored ); + } ); } if ( l ) { - fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); first = fragment.firstChild; if ( fragment.childNodes.length === 1 ) { fragment = first; } - if ( first ) { + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); hasScripts = scripts.length; - // Use the original fragment for the last item instead of the first because it can end up + // Use the original fragment for the last item + // instead of the first because it can end up // being emptied incorrectly in certain situations (#8070). for ( ; i < l; i++ ) { node = fragment; @@ -5957,11 +6079,14 @@ jQuery.fn.extend({ // Keep references to cloned scripts for later restoration if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit jQuery.merge( scripts, getAll( node, "script" ) ); } } - callback.call( this[i], node, i ); + callback.call( collection[ i ], node, i ); } if ( hasScripts ) { @@ -5974,206 +6099,507 @@ jQuery.fn.extend({ for ( i = 0; i < hasScripts; i++ ) { node = scripts[ i ]; if ( rscriptType.test( node.type || "" ) && - !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { - if ( node.src ) { // Optional AJAX dependency, but won't run scripts if not present - if ( jQuery._evalUrl ) { - jQuery._evalUrl( node.src ); + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); } } else { - jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); } } } } - - // Fix #11809: Avoid leaking memory - fragment = first = null; } } - return this; + return collection; } -}); - -jQuery.each({ - appendTo: "append", - prependTo: "prepend", - insertBefore: "before", - insertAfter: "after", - replaceAll: "replaceWith" -}, function( name, original ) { - jQuery.fn[ name ] = function( selector ) { - var elems, - i = 0, - ret = [], - insert = jQuery( selector ), - last = insert.length - 1; - for ( ; i <= last; i++ ) { - elems = i === last ? this : this.clone(true); - jQuery( insert[i] )[ original ]( elems ); + function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } - // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() - push.apply( ret, elems.get() ); + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } } - return this.pushStack( ret ); - }; -}); + return elem; + } + jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, -var iframe, - elemdisplay = {}; + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); -/** - * Retrieve the actual display of a element - * @param {String} name nodeName of the element - * @param {Object} doc Document object - */ -// Called only from within defaultDisplay -function actualDisplay( name, doc ) { - var style, - elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { - // getDefaultComputedStyle might be reliably used only on attached element - display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ? + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); - // Use of this method is a temporary fix (more like optmization) until something better comes along, - // since it was removed from specification and supported only in FF - style.display : jQuery.css( elem[ 0 ], "display" ); + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } - // We don't have any data stored on the element, - // so use "detach" method as fast way to get rid of the element - elem.detach(); + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); - return display; -} + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } -/** - * Try to determine the default display value of an element - * @param {String} nodeName - */ -function defaultDisplay( nodeName ) { - var doc = document, - display = elemdisplay[ nodeName ]; + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } - if ( !display ) { - display = actualDisplay( nodeName, doc ); + // Return the cloned set + return clone; + }, - // If the simple way fails, read from inside an iframe - if ( display === "none" || !display ) { + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; - // Use the already-created iframe if possible - iframe = (iframe || jQuery( "