Merge commit '023dd440d4a0e6e59a14c88013837d79a77c74e0' into 1.1-merge

Conflicts:
	openid-connect-client/pom.xml
	openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/AuthorizationRequestImpl.java
	openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/IntrospectingTokenService.java
	openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/IntrospectionAuthorityGranter.java
	openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/IntrospectionUrlProvider.java
	openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java
	openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationProvider.java
	openid-connect-client/src/main/java/org/mitre/openid/connect/client/keypublisher/ClientKeyPublisher.java
	openid-connect-client/src/main/java/org/mitre/openid/connect/client/keypublisher/ClientKeyPublisherMapping.java
	openid-connect-client/src/main/java/org/mitre/openid/connect/client/keypublisher/JwkViewResolver.java
	openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/AuthRequestUrlBuilder.java
	openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/ClientConfigurationService.java
	openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticClientConfigurationService.java
	openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticServerConfigurationService.java
	openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticSingleIssuerService.java
	openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/ThirdPartyIssuerService.java
	openid-connect-client/src/test/java/org/mitre/openid/connect/client/AbstractOIDCAuthenticationFilterTest.java
	openid-connect-common/pom.xml
	openid-connect-common/src/main/java/org/mitre/jose/keystore/JWKSetKeyStore.java
	openid-connect-common/src/main/java/org/mitre/jwt/signer/service/JwtSigningAndValidationService.java
	openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/DefaultJwtSigningAndValidationService.java
	openid-connect-common/src/main/java/org/mitre/jwt/signer/service/impl/JWKSetSigningAndValidationServiceCacheService.java
	openid-connect-common/src/main/java/org/mitre/oauth2/model/AuthorizationCodeEntity.java
	openid-connect-common/src/main/java/org/mitre/oauth2/model/ClientDetailsEntity.java
	openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2AccessTokenEntity.java
	openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2RefreshTokenEntity.java
	openid-connect-common/src/main/java/org/mitre/oauth2/model/SystemScope.java
	openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthorizationCodeRepository.java
	openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2TokenRepository.java
	openid-connect-common/src/main/java/org/mitre/oauth2/service/OAuth2TokenEntityService.java
	openid-connect-common/src/main/java/org/mitre/openid/connect/config/ConfigurationPropertiesBean.java
	openid-connect-common/src/main/java/org/mitre/openid/connect/config/ServerConfiguration.java
	openid-connect-common/src/main/java/org/mitre/openid/connect/model/ApprovedSite.java
	openid-connect-common/src/main/java/org/mitre/openid/connect/model/BlacklistedSite.java
	openid-connect-common/src/main/java/org/mitre/openid/connect/model/Event.java
	openid-connect-common/src/main/java/org/mitre/openid/connect/model/OIDCAuthenticationToken.java
	openid-connect-common/src/main/java/org/mitre/openid/connect/model/WhitelistedSite.java
	openid-connect-common/src/main/java/org/mitre/util/jpa/JpaUtil.java
	openid-connect-server/.gitignore
	openid-connect-server/pom.xml
	openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaAuthorizationCodeRepository.java
	openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2AuthorizationCodeService.java
	openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ClientDetailsEntityService.java
	openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java
	openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultSystemScopeService.java
	openid-connect-server/src/main/java/org/mitre/oauth2/token/ChainedTokenGranter.java
	openid-connect-server/src/main/java/org/mitre/oauth2/token/JwtAssertionTokenGranter.java
	openid-connect-server/src/main/java/org/mitre/oauth2/view/TokenIntrospectionView.java
	openid-connect-server/src/main/java/org/mitre/oauth2/web/IntrospectionEndpoint.java
	openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java
	openid-connect-server/src/main/java/org/mitre/oauth2/web/RevocationEndpoint.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/ConnectOAuth2RequestFactory.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JwtBearerAuthenticationProvider.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/assertion/JwtBearerClientAssertionTokenEndpointFilter.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/exception/InvalidJwtSignatureException.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/exception/UnknownUserInfoSchemaException.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/exception/UserNotFoundException.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaApprovedSiteRepository.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaUserInfoRepository.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultApprovedSiteService.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultNonceService.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultStatsService.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultUserInfoUserDetailsService.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultWhitelistedSiteService.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/token/ConnectTokenEnhancer.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/token/TofuUserApprovalHandler.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/view/AbstractClientEntityView.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/view/ClientInformationResponseView.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/view/ExceptionAsJSONView.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonEntityView.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/view/JsonErrorView.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/view/POCOUserInfoView.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/view/StatsSummary.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/view/UserInfoView.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/web/ApprovedSiteAPI.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/web/BlacklistAPI.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientDynamicRegistrationEndpoint.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/web/ManagerController.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/web/RequestObjectAuthorizationEndpoint.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/web/StatsAPI.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/web/UserInfoEndpoint.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/web/UserInfoInterceptor.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/web/WhitelistAPI.java
	openid-connect-server/src/main/webapp/WEB-INF/tags/aboutContent.tag
	openid-connect-server/src/main/webapp/WEB-INF/tags/breadcrumbs.tag
	openid-connect-server/src/main/webapp/WEB-INF/tags/contactContent.tag
	openid-connect-server/src/main/webapp/WEB-INF/tags/copyright.tag
	openid-connect-server/src/main/webapp/WEB-INF/tags/header.tag
	openid-connect-server/src/main/webapp/WEB-INF/tags/landingPageAbout.tag
	openid-connect-server/src/main/webapp/WEB-INF/tags/landingPageContact.tag
	openid-connect-server/src/main/webapp/WEB-INF/tags/landingPageStats.tag
	openid-connect-server/src/main/webapp/WEB-INF/tags/landingPageWelcome.tag
	openid-connect-server/src/main/webapp/WEB-INF/tags/sidebar.tag
	openid-connect-server/src/main/webapp/WEB-INF/tags/statsContent.tag
	openid-connect-server/src/main/webapp/WEB-INF/tags/topbar.tag
	openid-connect-server/src/main/webapp/WEB-INF/views/about.jsp
	openid-connect-server/src/main/webapp/WEB-INF/views/approve.jsp
	openid-connect-server/src/main/webapp/WEB-INF/views/contact.jsp
	openid-connect-server/src/main/webapp/WEB-INF/views/exception/usernotfound.jsp
	openid-connect-server/src/main/webapp/WEB-INF/views/login.jsp
	openid-connect-server/src/main/webapp/WEB-INF/views/manage.jsp
	openid-connect-server/src/main/webapp/WEB-INF/views/stats.jsp
	pom.xml
pull/477/head
Justin Richer 2013-07-29 16:21:20 -04:00
commit 856c0ea0b5
242 changed files with 10369 additions and 2258 deletions

View File

@ -1,7 +1 @@
language: java
before_install:
- git submodule update --init --recursive
jdk:
- openjdk6
install: echo 'skip this step...'
script: mvn -Dmaven.javadoc.skip=true test

View File

@ -1,9 +1,33 @@
An OpenID Connect reference implementation in Java on the Spring platform.
An OpenID Connect reference implementation in Java on the Spring platform. For license information see LICENSE.txt.
This code includes a functioning server (IdP) and client (RP) as well as utility libraries.
Authors: Justin Richer, Amanda Anganes, Michael Walsh, Michael Jett, Steve Moore, Mike Derryberry
The project homepage on GitHub is:
Copyright 2012, The MITRE Corporation (http://www.mitre.org/)
https://github.com/mitreid-connect/
Full documentation can be found online:
https://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server/wiki
Documentation for the Maven project and Java API can be found at:
http://mitreid-connect.github.com/
Issues can be reported at:
https://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server/issues
The mailing list for the project can be found at mitreid-connect@mit.edu, with archives available online:
https://mailman.mit.edu/mailman/listinfo/mitreid-connect
Authors: Justin Richer, Amanda Anganes, Michael Walsh, Michael Jett, Steve Moore, Mike Derryberry, William Kim
Copyright 2013, The MITRE Corporation (http://www.mitre.org/)
and the MIT Kerberos and Internet Trust Consortium (http://kit.mit.edu/)

302
checkstyle.xml Normal file
View File

@ -0,0 +1,302 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
<!-- This is a checkstyle configuration file. For descriptions of what the
following rules do, please see the checkstyle configuration page at http://checkstyle.sourceforge.net/config.html -->
<!-- Adapted from google-api-java-client -->
<module name="Checker">
<module name="NewlineAtEndOfFile">
<property name="lineSeparator" value="lf"/>
</module>
<module name="RegexpSingleline">
<!-- Checks that FIXME is not used in comments. TODO is preferred. -->
<property name="format" value="((//.*)|(\*.*))FIXME"/>
<property name="message" value='TODO is preferred to FIXME.'/>
<property name="severity" value="warning"/>
</module>
<!-- All Java AST specific tests live under TreeWalker module. -->
<module name="TreeWalker">
<!-- IMPORT CHECKS -->
<module name="RedundantImport">
<!-- Checks for redundant import statements. -->
<property name="severity" value="error"/>
</module>
<module name="ImportOrder">
<!-- Checks for out of order import statements. -->
<property name="severity" value="warning"/>
<!-- This ensures that static imports go first. -->
<property name="option" value="top"/>
<property name="tokens" value="STATIC_IMPORT, IMPORT"/>
</module>
<module name="AvoidStarImport">
<property name="severity" value="warning"/>
</module>
<module name="UnusedImports"/>
<!-- JAVADOC CHECKS -->
<!-- Checks for Javadoc comments. -->
<!-- See http://checkstyle.sf.net/config_javadoc.html -->
<module name="JavadocStyle">
<property name="severity" value="warning"/>
</module>
<!-- NAMING CHECKS -->
<!-- Item 38 - Adhere to generally accepted naming conventions -->
<module name="PackageName">
<!-- Validates identifiers for package names against the supplied expression. -->
<!-- Here the default checkstyle rule restricts package name parts to
seven characters, this is not in line with common practice at Google. -->
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]{1,})*$"/>
<property name="severity" value="warning"/>
</module>
<module name="TypeNameCheck">
<!-- Validates static, final fields against the expression "^[A-Z][a-zA-Z0-9]*$". -->
<metadata name="altname" value="TypeName"/>
<property name="severity" value="warning"/>
</module>
<module name="ConstantNameCheck">
<!-- Validates non-private, static, final fields against the supplied
public/package final fields "^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$". -->
<metadata name="altname" value="ConstantName"/>
<property name="applyToPublic" value="true"/>
<property name="applyToProtected" value="true"/>
<property name="applyToPackage" value="true"/>
<property name="applyToPrivate" value="false"/>
<property name="format" value="^([A-Z][A-Z0-9]*(_[A-Z0-9]+)*|FLAG_.*)$"/>
<message key="name.invalidPattern"
value="Variable ''{0}'' should be in ALL_CAPS (if it is a constant) or be private (otherwise)."/>
<property name="severity" value="warning"/>
</module>
<module name="StaticVariableNameCheck">
<!-- Validates static, non-final fields against the supplied expression
"^[a-z][a-zA-Z0-9]*_?$". -->
<metadata name="altname" value="StaticVariableName"/>
<property name="applyToPublic" value="true"/>
<property name="applyToProtected" value="true"/>
<property name="applyToPackage" value="true"/>
<property name="applyToPrivate" value="true"/>
<property name="format" value="^[a-z][a-zA-Z0-9]*_?$"/>
<property name="severity" value="warning"/>
</module>
<module name="MemberNameCheck">
<!-- Validates non-static members against the supplied expression. -->
<metadata name="altname" value="MemberName"/>
<property name="applyToPublic" value="true"/>
<property name="applyToProtected" value="true"/>
<property name="applyToPackage" value="true"/>
<property name="applyToPrivate" value="true"/>
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
<property name="severity" value="warning"/>
</module>
<module name="MethodNameCheck">
<!-- Validates identifiers for method names. -->
<metadata name="altname" value="MethodName"/>
<property name="format" value="^[a-z][a-zA-Z0-9]*(_[a-zA-Z0-9]+)*$"/>
<property name="severity" value="warning"/>
</module>
<module name="ParameterName">
<!-- Validates identifiers for method parameters against the expression
"^[a-z][a-zA-Z0-9]*$". -->
<property name="severity" value="warning"/>
</module>
<module name="LocalFinalVariableName">
<!-- Validates identifiers for local final variables against the expression
"^[a-z][a-zA-Z0-9]*$". -->
<property name="severity" value="warning"/>
</module>
<module name="LocalVariableName">
<!-- Validates identifiers for local variables against the expression
"^[a-z][a-zA-Z0-9]*$". -->
<property name="severity" value="warning"/>
</module>
<!-- LENGTH and CODING CHECKS -->
<module name="LineLength">
<!-- Checks if a line is too long. -->
<property name="max"
value="${com.puppycrawl.tools.checkstyle.checks.sizes.LineLength.max}"
default="250"/>
<property name="severity" value="warning"/>
<!-- The default ignore pattern exempts the following elements: - import
statements - long URLs inside comments -->
<property name="ignorePattern"
value="${com.puppycrawl.tools.checkstyle.checks.sizes.LineLength.ignorePattern}"
default="^(package .*;\s*)|(import .*;\s*)|( *\* *https?://.*)$"/>
</module>
<module name="LeftCurly">
<!-- Checks for placement of the left curly brace ('{'). -->
<property name="severity" value="warning"/>
</module>
<module name="RightCurly">
<!-- Checks right curlies on CATCH, ELSE, and TRY blocks are on the same
line. e.g., the following example is fine: <pre> if { ... } else </pre> -->
<!-- This next example is not fine: <pre> if { ... } else </pre> -->
<property name="option" value="same"/>
<property name="severity" value="warning"/>
</module>
<!-- Checks for braces around if and else blocks -->
<module name="NeedBraces">
<property name="severity" value="warning"/>
<property name="tokens"
value="LITERAL_IF, LITERAL_ELSE, LITERAL_FOR, LITERAL_WHILE, LITERAL_DO"/>
</module>
<module name="UpperEll">
<!-- Checks that long constants are defined with an upper ell. -->
<property name="severity" value="error"/>
</module>
<module name="FallThrough">
<!-- Warn about falling through to the next case statement. Similar to
javac -Xlint:fallthrough, but the check is suppressed if a single-line comment
on the last non-blank line preceding the fallen-into case contains 'fall
through' (or some other variants which we don't publicized to promote consistency). -->
<property name="reliefPattern"
value="fall through|Fall through|fallthru|Fallthru|falls through|Falls through|fallthrough|Fallthrough|No break|NO break|no break|continue on"/>
<property name="severity" value="error"/>
</module>
<module name="AnnotationUseStyle">
<property name="severity" value="warning"/>
</module>
<module name="ArrayTypeStyle">
<property name="severity" value="warning"/>
</module>
<module name="AvoidNestedBlocks">
<property name="severity" value="error"/>
</module>
<module name="CovariantEquals">
<property name="severity" value="error"/>
</module>
<module name="DeclarationOrder">
<property name="severity" value="warning"/>
</module>
<module name="DefaultComesLast">
<property name="severity" value="warning"/>
</module>
<module name="EmptyStatement">
<property name="severity" value="warning"/>
</module>
<module name="MultipleStringLiterals">
<property name="allowedDuplicates" value="1"/>
<property name="severity" value="warning"/>
</module>
<module name="NeedBraces">
<property name="severity" value="error"/>
</module>
<module name="PackageDeclaration"/>
<!-- COMPLEXITY CHECKS -->
<module name="BooleanExpressionComplexity">
<property name="max" value="10"/>
<property name="severity" value="warning"/>
</module>
<module name="CyclomaticComplexity">
<property name="max" value="10"/>
<property name="severity" value="warning"/>
</module>
<module name="NPathComplexity">
<property name="max" value="200"/>
<property name="severity" value="warning"/>
</module>
<!-- MODIFIERS CHECKS -->
<module name="ModifierOrder">
<!-- Warn if modifier order is inconsistent with JLS3 8.1.1, 8.3.1, and
8.4.3. The prescribed order is: public, protected, private, abstract, static,
final, transient, volatile, synchronized, native, strictfp -->
</module>
<!-- WHITESPACE CHECKS -->
<module name="WhitespaceAround">
<!-- Checks that various tokens are surrounded by whitespace. This includes
most binary operators and keywords followed by regular or curly braces. -->
<property name="tokens"
value="ASSIGN, BAND, BAND_ASSIGN, BOR,
BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR, BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN,
EQUAL, GE, GT, LAND, LE, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE,
LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF, LITERAL_RETURN,
LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, LOR, LT, MINUS,
MINUS_ASSIGN, MOD, MOD_ASSIGN, NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION,
SL, SL_ASSIGN, SR_ASSIGN, STAR, STAR_ASSIGN"/>
<property name="severity" value="warning"/>
</module>
<module name="WhitespaceAfter">
<!-- Checks that commas, semicolons and typecasts are followed by whitespace. -->
<property name="tokens" value="COMMA, SEMI, TYPECAST"/>
<property name="severity" value="warning"/>
</module>
<module name="NoWhitespaceAfter">
<!-- Checks that there is no whitespace after various unary operators.
Linebreaks are allowed. -->
<property name="tokens"
value="BNOT, DEC, DOT, INC, LNOT, UNARY_MINUS, UNARY_PLUS"/>
<property name="allowLineBreaks" value="true"/>
<property name="severity" value="warning"/>
</module>
<module name="NoWhitespaceBefore">
<!-- Checks that there is no whitespace before various unary operators.
Linebreaks are allowed. -->
<property name="tokens" value="SEMI, DOT, POST_DEC, POST_INC"/>
<property name="allowLineBreaks" value="true"/>
<property name="severity" value="warning"/>
</module>
<module name="ParenPad">
<!-- Checks that there is no whitespace before close parens or after open
parens. -->
<property name="severity" value="warning"/>
</module>
</module>
</module>

View File

@ -1,46 +0,0 @@
This project is built on Spring 3.1 and Spring Security 3.1, making heavy use of the OAuth2 module of Spring Security OAuth (SECOAUTH). Wherever sensible, we have tried to make use of existing functionality in SECOAUTH, Spring, and Spring Security.
This project tracks against the development version of SECOAUTH, which is included in the build directories as a Git submodule. This submodule must be initialized before the main project can be built. Once SECOAUTH stabilizes to sufficient point, this project will remove its submodule reference and instead use a Maven dependency.
To initialize the submodule:
git submodule init
git submodule update
This project is intended to be a standalone OpenID Connect Server. Extension and customization of this server can be accomplished by configuration through Spring configuration files, injected functionality through new Beans, and overlay of views and static resources (using Maven War Overlay or similar functionality).
There is a JWT library that handles serialization/deserialization and manipulation of JWTs. We have our own implementation of OAuth2AccessToken called OAuth2AccessTokenEntity which is backed by a JWT object and returns the serialized version of the JWT as the token's Value field.
Managing users:
UserDetailsService - used by Spring Security's AuthenticationProvider to represent the current user (loads a user from a given user id)
AuthenticationUserDetailsService - Used by Spring Security to load a user from an authentication token
UserInfoRepository - repository of user information that is fed into the UserInfoEndpoint's service
Managing OAuth tokens:
AuthorizationServerTokenServices - provide tokens for the authorization server
Managing OAuth clients:
ClientDetailsService - provide OAuth client information (used for OpenID Connect Clients)
Modules
-------
The project uses a multi-level Maven and git repository sutrcture. The main project is split into the following modules:
- openid-connect-common: common classes, service and repository interfaces, and model code. Also includes full JWT library.
- openid-connect-server: IdP/server implementation, includes implementations of services and repositories for use by server.
- openid-connect-client: RP/client implementation, built around spring security filters.
- spring-security-oauth: Git submodule that points to the Spring Security OAuth Git repository. Will be removed once a reliable milestone is reached upstream (see note above).
Maven War Overlay
-----------------
One of the best ways to build a custom deployment of this system is to use the Maven War Overlay mechanism. In essence, you make a new Maven project with a "war" disposition and make it depend on the openid-connect-server module with the Maven Overlay plugin configured. Any files in your new project will be built and injected into the war from the other project. This action will also overwrite any existing files.
For instance, to overwrite the data source configuration in the main server war file, create a file named src/main/webapp/WEB-INF/data-context.xml that contains the dataSource bean. This file will completely replace the one that's in the originally built war.

BIN
docs/OAuth2.0_Diagrams.pdf Normal file → Executable file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 191 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

View File

@ -1,39 +0,0 @@
Changelog
Updated on 3/6/2012
Connect:
* "Authorization Code Flow" diagram: changed step B to be a redirect rather than a JSON response object.
Updated on 2/21/2012
OAuth2:
* Renamed "Access Code Flow" to "Authorization Code Flow".
* Changed all references to "User" to "Resource Owner".
* Changed final "Response"s to "JSON respones object"s.
* Added initial "Authenticate Resource Owner" step to Authorization Code Flow
Connect:
* Changed final "Response"s to "JSON respones object"s.
Updated on 2/7/2012
OAuth2:
* Removed refresh_token from the Access Token response on the Client Credentials flow.
Ref: http://tools.ietf.org/html/draft-ietf-oauth-v2-23#section-4.4.3
"A refresh token SHOULD NOT be included."
* Changed "Consumer" to "Client".
Connect:
* Changed "Consumer" to "Client".
* Clarified required/optional wording. Parameters are REQUIRED unless otherwise stated.
* Implicit Flow: changed wording on redirect_uri requirement in the Authorization Request. Now reads "required IFF the client has pre-configured more than one value with the service provider".
* Diagram 3 was renamed to "Optional Steps" (from "Additional Steps"), as these steps may or may not be taken and may be done in any order. Added "openid" to the schema parameter in the UserInfo Request.

View File

@ -1,6 +1,20 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!--
Copyright 2013 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
@ -12,7 +26,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
<groupId>org.mitre</groupId>
<artifactId>openid-connect-client</artifactId>
<version>1.1.0-SNAPSHOT</version>
<description>OpenID Connect Client Files</description>
<description>OpenID Connect Client filter for Spring Security</description>
<name>OpenID Connect Client</name>
<dependencies>
<dependency>
@ -20,11 +34,6 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
<artifactId>openid-connect-common</artifactId>
<version>1.1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<version>1.1.0.M1</version>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
</dependencies>
<packaging>jar</packaging>
<build>

View File

@ -1,3 +1,20 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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;
import java.util.Date;
@ -9,7 +26,6 @@ import java.util.Set;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.util.OAuth2Utils;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
@ -25,30 +41,33 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
/**
* This ResourceServerTokenServices implementation introspects incoming tokens at a
* server's introspection endpoint URL and passes an Authentication object along
* based on the response from the introspection endpoint.
* @author jricher
*
*/
public class IntrospectingTokenService implements ResourceServerTokenServices {
private String clientId;
private String clientSecret;
private String introspectionUrl;
private IntrospectionUrlProvider introspectionUrlProvider;
private IntrospectionAuthorityGranter introspectionAuthorityGranter = new SimpleIntrospectionAuthorityGranter();
// Inner class to store in the hash map
private class TokenCacheObject { OAuth2AccessToken token; OAuth2Authentication auth;
private TokenCacheObject(OAuth2AccessToken token, OAuth2Authentication auth) {
this.token = token;
this.auth = auth;
}
private class TokenCacheObject {
OAuth2AccessToken token;
OAuth2Authentication auth;
private TokenCacheObject(OAuth2AccessToken token, OAuth2Authentication auth) {
this.token = token;
this.auth = auth;
}
}
private Map<String, TokenCacheObject> authCache = new HashMap<String, TokenCacheObject>();
public String getIntrospectionUrl() {
return introspectionUrl;
}
public void setIntrospectionUrl(String introspectionUrl) {
this.introspectionUrl = introspectionUrl;
}
public String getClientId() {
return clientId;
}
@ -65,10 +84,24 @@ public class IntrospectingTokenService implements ResourceServerTokenServices {
this.clientSecret = clientSecret;
}
/**
* @return the introspectionUrlProvider
*/
public IntrospectionUrlProvider getIntrospectionUrlProvider() {
return introspectionUrlProvider;
}
/**
* @param introspectionUrlProvider the introspectionUrlProvider to set
*/
public void setIntrospectionUrlProvider(IntrospectionUrlProvider introspectionUrlProvider) {
this.introspectionUrlProvider = introspectionUrlProvider;
}
// Check if there is a token and authentication in the cache
// and check if it is not expired.
// and check if it is not expired.
private TokenCacheObject checkCache(String key) {
if(authCache.containsKey(key)) {
if (authCache.containsKey(key)) {
TokenCacheObject tco = authCache.get(key);
if (tco.token.getExpiration().after(new Date())) {
return tco;
@ -91,30 +124,31 @@ public class IntrospectingTokenService implements ResourceServerTokenServices {
parameters.put("scope", OAuth2Utils.formatParameterList(scopes));
OAuth2Request storedRequest = new OAuth2Request(parameters, clientId, null, true, scopes, null, null, null);
return storedRequest;
}
// create a default authentication object with authority ROLE_API
private Authentication createAuthentication(JsonObject token){
// TODO: make role/authority configurable somehow
return new PreAuthenticatedAuthenticationToken(token.get("subject").getAsString(), null, AuthorityUtils.createAuthorityList("ROLE_API"));
private Authentication createAuthentication(JsonObject token) {
return new PreAuthenticatedAuthenticationToken(token.get("sub").getAsString(), token, introspectionAuthorityGranter.getAuthorities(token));
}
private OAuth2AccessToken createAccessToken(final JsonObject token, final String tokenString){
private OAuth2AccessToken createAccessToken(final JsonObject token, final String tokenString) {
OAuth2AccessToken accessToken = new OAuth2AccessTokenImpl(token, tokenString);
return accessToken;
}
// Validate a token string against the introspection endpoint,
// then parse it and store it in the local cache. Return true on
// sucess, false otherwise.
// then parse it and store it in the local cache. Return true on
// sucess, false otherwise.
private boolean parseToken(String accessToken) {
String validatedToken = null;
// Use the SpringFramework RestTemplate to send the request to the endpoint
// find out which URL to ask
String introspectionUrl = introspectionUrlProvider.getIntrospectionUrl(accessToken);
// Use the SpringFramework RestTemplate to send the request to the
// endpoint
String validatedToken = null;
RestTemplate restTemplate = new RestTemplate();
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
form.add("token",accessToken);
form.add("token", accessToken);
form.add("client_id", this.clientId);
form.add("client_secret", this.clientSecret);
@ -138,7 +172,7 @@ public class IntrospectingTokenService implements ResourceServerTokenServices {
return false;
}
if (!tokenResponse.get("valid").getAsBoolean()){
if (!tokenResponse.get("active").getAsBoolean()) {
// non-valid token
return false;
}
@ -147,9 +181,9 @@ public class IntrospectingTokenService implements ResourceServerTokenServices {
// create an OAuth2AccessToken
OAuth2AccessToken token = createAccessToken(tokenResponse, accessToken);
if (token.getExpiration().after(new Date())){
if (token.getExpiration().after(new Date())) {
// Store them in the cache
authCache.put(accessToken, new TokenCacheObject(token,auth));
authCache.put(accessToken, new TokenCacheObject(token, auth));
return true;
}
@ -161,7 +195,8 @@ public class IntrospectingTokenService implements ResourceServerTokenServices {
@Override
public OAuth2Authentication loadAuthentication(String accessToken) throws AuthenticationException {
// First check if the in memory cache has an Authentication object, and that it is still valid
// First check if the in memory cache has an Authentication object, and
// that it is still valid
// If Valid, return it
TokenCacheObject cacheAuth = checkCache(accessToken);
if (cacheAuth != null) {
@ -182,7 +217,8 @@ public class IntrospectingTokenService implements ResourceServerTokenServices {
@Override
public OAuth2AccessToken readAccessToken(String accessToken) {
// First check if the in memory cache has a Token object, and that it is still valid
// First check if the in memory cache has a Token object, and that it is
// still valid
// If Valid, return it
TokenCacheObject cacheAuth = checkCache(accessToken);
if (cacheAuth != null) {

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,22 +13,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.mitre.openid.connect.exception;
/**
* @author aanganes, nemonik
*
*/
package org.mitre.oauth2.introspectingfilter;
import java.util.List;
import org.springframework.security.core.GrantedAuthority;
import com.google.gson.JsonObject;
/**
* @author jricher
*
*/
public class InvalidJwtSignatureException extends RuntimeException {
public interface IntrospectionAuthorityGranter {
private static final long serialVersionUID = 1L;
public InvalidJwtSignatureException() {
super();
}
public InvalidJwtSignatureException(String message) {
super(message);
}
public List<GrantedAuthority> getAuthorities(JsonObject introspectionResponse);
}

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,22 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.mitre.openid.connect.exception;
/**
* @author aanganes, nemonik
*
*/
package org.mitre.oauth2.introspectingfilter;
/**
* @author jricher
*
*/
public class UnknownUserInfoSchemaException extends RuntimeException {
public interface IntrospectionUrlProvider {
private static final long serialVersionUID = 1L;
public UnknownUserInfoSchemaException() {
super();
}
public UnknownUserInfoSchemaException(String message) {
super(message);
}
/**
* Get the introspection URL based on the access token.
* @param accessToken
* @return
*/
public String getIntrospectionUrl(String accessToken);
}

View File

@ -0,0 +1,93 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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;
import java.text.ParseException;
import org.mitre.openid.connect.client.service.ServerConfigurationService;
import org.mitre.openid.connect.config.ServerConfiguration;
import com.google.common.base.Strings;
import com.nimbusds.jwt.JWT;
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
*
*/
public class JWTParsingIntrospectionUrlProvider implements IntrospectionUrlProvider {
private ServerConfigurationService serverConfigurationService;
/**
* @return the serverConfigurationService
*/
public ServerConfigurationService getServerConfigurationService() {
return serverConfigurationService;
}
/**
* @param serverConfigurationService the serverConfigurationService to set
*/
public void setServerConfigurationService(ServerConfigurationService serverConfigurationService) {
this.serverConfigurationService = serverConfigurationService;
}
/* (non-Javadoc)
* @see org.mitre.oauth2.introspectingfilter.IntrospectionUrlProvider#getIntrospectionUrl(java.lang.String)
*/
@Override
public String getIntrospectionUrl(String accessToken) {
try {
JWT jwt = JWTParser.parse(accessToken);
String issuer = jwt.getJWTClaimsSet().getIssuer();
if (!Strings.isNullOrEmpty(issuer)) {
ServerConfiguration server = serverConfigurationService.getServerConfiguration(issuer);
if (server != null) {
if (!Strings.isNullOrEmpty(server.getIntrospectionEndpointUri())) {
return server.getIntrospectionEndpointUri();
} else {
throw new IllegalArgumentException("Server does not have Introspection Endpoint defined");
}
} else {
throw new IllegalArgumentException("Could not find server configuration for issuer " + issuer);
}
} else {
throw new IllegalArgumentException("No issuer claim found in JWT");
}
} catch (ParseException e) {
throw new IllegalArgumentException("Unable to parse JWT", e);
}
}
}

View File

@ -1,3 +1,20 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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;
import java.text.DateFormat;

View File

@ -0,0 +1,63 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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;
import java.util.List;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import com.google.gson.JsonObject;
/**
*
* Grants the same set of authorities no matter what's passed in.
*
* @author jricher
*
*/
public class SimpleIntrospectionAuthorityGranter implements IntrospectionAuthorityGranter {
private List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("ROLE_API");
/* (non-Javadoc)
* @see org.mitre.oauth2.introspectingfilter.IntrospectionAuthorityGranter#getAuthorities(net.minidev.json.JSONObject)
*/
@Override
public List<GrantedAuthority> getAuthorities(JsonObject introspectionResponse) {
return authorities;
}
/**
* @return the authorities
*/
public List<GrantedAuthority> getAuthorities() {
return authorities;
}
/**
* @param authorities the authorities to set
*/
public void setAuthorities(List<GrantedAuthority> authorities) {
this.authorities = authorities;
}
}

View File

@ -0,0 +1,57 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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;
/**
*
* Always provides the (configured) IntrospectionURL regardless of token. Useful for talking to
* a single, trusted authorization server.
*
* @author jricher
*
*/
public class StaticIntrospectionUrlProvider implements IntrospectionUrlProvider {
private String introspectionUrl;
/**
* @return the introspectionUrl
*/
public String getIntrospectionUrl() {
return introspectionUrl;
}
/**
* @param introspectionUrl the introspectionUrl to set
*/
public void setIntrospectionUrl(String introspectionUrl) {
this.introspectionUrl = introspectionUrl;
}
/* (non-Javadoc)
* @see org.mitre.oauth2.introspectingfilter.IntrospectionUrlProvider#getIntrospectionUrl(java.lang.String)
*/
@Override
public String getIntrospectionUrl(String accessToken) {
return getIntrospectionUrl();
}
}

View File

@ -0,0 +1,96 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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 java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
/**
*
* 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 GrantedAuthoritiesMapper {
private static final SimpleGrantedAuthority ROLE_ADMIN = new SimpleGrantedAuthority("ROLE_ADMIN");
private static final SimpleGrantedAuthority ROLE_USER = new SimpleGrantedAuthority("ROLE_USER");
private Set<SubjectIssuerGrantedAuthority> admins = new HashSet<SubjectIssuerGrantedAuthority>();
private GrantedAuthoritiesMapper chain = new NullAuthoritiesMapper();
@Override
public Collection<? extends GrantedAuthority> mapAuthorities(Collection<? extends GrantedAuthority> authorities) {
Set<GrantedAuthority> out = new HashSet<GrantedAuthority>();
out.addAll(authorities);
for (GrantedAuthority authority : authorities) {
if (admins.contains(authority)) {
out.add(ROLE_ADMIN);
}
}
// everybody's a user by default
out.add(ROLE_USER);
return chain.mapAuthorities(out);
}
/**
* @return the admins
*/
public Set<SubjectIssuerGrantedAuthority> getAdmins() {
return admins;
}
/**
* @param admins the admins to set
*/
public void setAdmins(Set<SubjectIssuerGrantedAuthority> admins) {
this.admins = admins;
}
/**
* @return the chain
*/
public GrantedAuthoritiesMapper getChain() {
return chain;
}
/**
* @param chain the chain to set
*/
public void setChain(GrantedAuthoritiesMapper chain) {
this.chain = chain;
}
}

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,10 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.mitre.openid.connect.client;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URI;
import java.security.SecureRandom;
import java.text.ParseException;
import java.util.Date;
@ -26,22 +29,24 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang.StringUtils;
import org.apache.http.impl.client.DefaultHttpClient;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.mitre.jwt.signer.service.impl.JWKSetSigningAndValidationServiceCacheService;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.client.model.IssuerServiceResponse;
import org.mitre.openid.connect.client.service.AuthRequestUrlBuilder;
import org.mitre.openid.connect.client.service.ClientConfigurationService;
import org.mitre.openid.connect.client.service.IssuerService;
import org.mitre.openid.connect.client.service.ServerConfigurationService;
import org.mitre.openid.connect.config.ServerConfiguration;
import org.mitre.openid.connect.model.OIDCAuthenticationToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@ -52,9 +57,12 @@ import com.google.common.base.Strings;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.nimbusds.jose.util.Base64;
import com.nimbusds.jwt.ReadOnlyJWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import static org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod.*;
/**
* OpenID Connect Authentication Filter class
*
@ -148,18 +156,44 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
IssuerServiceResponse issResp = issuerService.getIssuer(request);
if (issResp == null) {
logger.error("Null issuer response returned from service.");
throw new AuthenticationServiceException("No issuer found.");
}
if (issResp.shouldRedirect()) {
response.sendRedirect(issResp.getRedirectUrl());
} else {
String issuer = issResp.getIssuer();
if (Strings.isNullOrEmpty(issuer)) {
logger.error("No issuer found: " + issuer);
throw new AuthenticationServiceException("No issuer found: " + issuer);
}
session.setAttribute(ISSUER_SESSION_VARIABLE, issuer);
ServerConfiguration serverConfig = servers.getServerConfiguration(issuer);
ClientDetails clientConfig = clients.getClientConfiguration(issuer);
if (serverConfig == null) {
logger.error("No server configuration found for issuer: " + issuer);
throw new AuthenticationServiceException("No server configuration found for issuer: " + issuer);
}
// our redirect URI is this current URL, with no query parameters
String redirectUri = request.getRequestURL().toString();
RegisteredClient clientConfig = clients.getClientConfiguration(serverConfig);
if (clientConfig == null) {
logger.error("No client configuration found for issuer: " + issuer);
throw new AuthenticationServiceException("No client configuration found for issuer: " + issuer);
}
String redirectUri = null;
if (clientConfig.getRegisteredRedirectUri() != null && clientConfig.getRegisteredRedirectUri().size() == 1) {
// if there's a redirect uri configured (and only one), use that
redirectUri = clientConfig.getRegisteredRedirectUri().toArray(new String[] {})[0];
} else {
// otherwise our redirect URI is this current URL, with no query parameters
redirectUri = request.getRequestURL().toString();
}
session.setAttribute(REDIRECT_URI_SESION_VARIABLE, redirectUri);
// this value comes back in the id token and is checked there
@ -191,7 +225,7 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
// check for state, if it doesn't match we bail early
String storedState = getStoredState(session);
if (!StringUtils.isBlank(storedState)) {
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);
@ -203,7 +237,7 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
// pull the configurations based on that issuer
ServerConfiguration serverConfig = servers.getServerConfiguration(issuer);
ClientDetails clientConfig = clients.getClientConfiguration(issuer);
final RegisteredClient clientConfig = clients.getClientConfiguration(serverConfig);
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
form.add("grant_type", "authorization_code");
@ -219,20 +253,31 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
httpClient.getParams().setParameter("http.socket.timeout", new Integer(httpSocketTimeout));
/* Use these for basic auth:
*
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(clientConfig.getClientId(), clientConfig.getClientSecret());
httpClient.getCredentialsProvider().setCredentials(AuthScope.ANY, credentials);
*/
/* Alternatively, use form-based auth:
*/
form.add("client_id", clientConfig.getClientId());
form.add("client_secret", clientConfig.getClientSecret());
/**/
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
RestTemplate restTemplate = new RestTemplate(factory);
RestTemplate restTemplate;
if (SECRET_BASIC.equals(clientConfig.getTokenEndpointAuthMethod())){
// use BASIC auth if configured to do so
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("Basic %s", Base64.encode(String.format("%s:%s", clientConfig.getClientId(), clientConfig.getClientSecret())) ));
return httpRequest;
}
};
} else { //Alternatively use form based auth
restTemplate = new RestTemplate(factory);
form.add("client_id", clientConfig.getClientId());
form.add("client_secret", clientConfig.getClientSecret());
}
logger.debug("tokenEndpointURI = " + serverConfig.getTokenEndpointUri());
logger.debug("form = " + form);
@ -359,9 +404,9 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
}
// compare the nonce to our stored claim
// FIXME: Nimbus claims as strings?
String nonce = (String) idClaims.getCustomClaim("nonce");
if (StringUtils.isBlank(nonce)) {
// would be nice to have a getClaimAsString() kind of method from nimbus..
String nonce = (String) idClaims.getClaim("nonce");
if (Strings.isNullOrEmpty(nonce)) {
logger.error("ID token did not contain a nonce claim.");

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,43 +13,32 @@
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.mitre.openid.connect.client;
import java.util.Collection;
import org.mitre.openid.connect.model.OIDCAuthenticationToken;
import org.mitre.openid.connect.model.UserInfo;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import com.google.common.base.Strings;
import com.google.common.collect.Sets;
import com.google.common.collect.Lists;
/**
* @author nemonik
*
*/
public class OIDCAuthenticationProvider implements
AuthenticationProvider, InitializingBean {
public class OIDCAuthenticationProvider implements AuthenticationProvider {
private UserInfoFetcher userInfoFetcher = new UserInfoFetcher();
private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();
/*
* (non-Javadoc)
*
* @see
* org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() throws Exception {
}
private GrantedAuthoritiesMapper authoritiesMapper = new NamedAdminAuthoritiesMapper();
/*
* (non-Javadoc)
@ -67,24 +56,22 @@ AuthenticationProvider, InitializingBean {
if (authentication instanceof OIDCAuthenticationToken) {
// Default authorities set
// TODO: let this be configured
Collection<SimpleGrantedAuthority> authorities = Sets.newHashSet(new SimpleGrantedAuthority("ROLE_USER"));
OIDCAuthenticationToken token = (OIDCAuthenticationToken) authentication;
Collection<SubjectIssuerGrantedAuthority> authorities = Lists.newArrayList(new SubjectIssuerGrantedAuthority(token.getSub(), token.getIssuer()));
UserInfo userInfo = userInfoFetcher.loadUserInfo(token);
if (userInfo == null) {
// TODO: user Info not found -- error?
} else {
if (!Strings.isNullOrEmpty(userInfo.getSub()) && !userInfo.getSub().equals(token.getUserId())) {
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: " + userInfo.getSub() + " / " + token.getUserId());
throw new UsernameNotFoundException("user_id mismatch between id_token and user_info call: " + userInfo.getSub() + " / " + token.getSub());
}
}
return new OIDCAuthenticationToken(token.getUserId(),
return new OIDCAuthenticationToken(token.getSub(),
token.getIssuer(),
userInfo, authoritiesMapper.mapAuthorities(authorities),
token.getIdTokenValue(), token.getAccessTokenValue(), token.getRefreshTokenValue());

View File

@ -0,0 +1,127 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.core.GrantedAuthority;
import com.google.common.base.Strings;
/**
*
* Simple authority representing a user at an issuer.
*
* @author jricher
*
*/
public class SubjectIssuerGrantedAuthority implements GrantedAuthority {
private static final long serialVersionUID = 5584978219226664794L;
private final String subject;
private final String issuer;
/**
* @param subject
* @param issuer
*/
public SubjectIssuerGrantedAuthority(String subject, String issuer) {
if (Strings.isNullOrEmpty(subject) || Strings.isNullOrEmpty(issuer)) {
throw new IllegalArgumentException("Neither subject nor issuer may be null or empty");
}
this.subject = subject;
this.issuer = 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
public String getAuthority() {
return "OIDC_" + subject + "_" + issuer;
}
/**
* @return the subject
*/
public String getSubject() {
return subject;
}
/**
* @return the issuer
*/
public String getIssuer() {
return issuer;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((issuer == null) ? 0 : issuer.hashCode());
result = prime * result + ((subject == null) ? 0 : subject.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 (!(obj instanceof SubjectIssuerGrantedAuthority)) {
return false;
}
SubjectIssuerGrantedAuthority other = (SubjectIssuerGrantedAuthority) obj;
if (issuer == null) {
if (other.issuer != null) {
return false;
}
} else if (!issuer.equals(other.issuer)) {
return false;
}
if (subject == null) {
if (other.subject != null) {
return false;
}
} else if (!subject.equals(other.subject)) {
return false;
}
return true;
}
@Override
public String toString() {
return getAuthority();
}
}

View File

@ -1,8 +1,26 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.mitre.openid.connect.model.DefaultUserInfo;
import org.mitre.openid.connect.model.OIDCAuthenticationToken;
import org.mitre.openid.connect.model.UserInfo;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.util.LinkedMultiValueMap;

View File

@ -1,6 +1,20 @@
/**
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
*/
* 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.keypublisher;
import java.util.Map;
@ -33,7 +47,7 @@ public class ClientKeyPublisher implements BeanDefinitionRegistryPostProcessor {
private String jwkViewName = "jwkKeyList";
/**
* If either the jwkPublishUrl or x509PublishUrl fields are set on this bean, set up a listener on that URL to publish keys.
* If the jwkPublishUrl field is set on this bean, set up a listener on that URL to publish keys.
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
@ -81,8 +95,6 @@ public class ClientKeyPublisher implements BeanDefinitionRegistryPostProcessor {
// map from key id to key
Map<String, JWK> keys = signingAndValidationService.getAllPublicKeys();
// TODO: check if keys are empty, return a 404 here or just an empty list?
return new ModelAndView(jwkViewName, "keys", keys);
}

View File

@ -1,3 +1,20 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.
******************************************************************************/
/**
*
*/
@ -18,7 +35,6 @@ import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMappi
public class ClientKeyPublisherMapping extends RequestMappingInfoHandlerMapping {
private String jwkPublishUrl;
private String x509PublishUrl;
/* (non-Javadoc)
* @see org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#isHandler(java.lang.Class)
@ -30,7 +46,6 @@ public class ClientKeyPublisherMapping extends RequestMappingInfoHandlerMapping
/**
* Map the "jwkKeyPublish" method to our jwkPublishUrl.
* Map the "x509KeyPublish" method to our x509PublishUrl.
*/
@Override
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
@ -44,15 +59,6 @@ public class ClientKeyPublisherMapping extends RequestMappingInfoHandlerMapping
null,
null,
null);
} else if (method.getName().equals("publishClientx509") && getX509PublishUrl() != null) {
return new RequestMappingInfo(
new PatternsRequestCondition(new String[] {getX509PublishUrl()}, getUrlPathHelper(), getPathMatcher(), false, false),
null,
null,
null,
null,
null,
null);
} else {
return null;
}
@ -73,18 +79,4 @@ public class ClientKeyPublisherMapping extends RequestMappingInfoHandlerMapping
this.jwkPublishUrl = jwkPublishUrl;
}
/**
* @return the x509PublishUrl
*/
public String getX509PublishUrl() {
return x509PublishUrl;
}
/**
* @param x509PublishUrl the x509PublishUrl to set
*/
public void setX509PublishUrl(String x509PublishUrl) {
this.x509PublishUrl = x509PublishUrl;
}
}

View File

@ -1,3 +1,20 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.
******************************************************************************/
/**
*
*/
@ -21,13 +38,10 @@ public class JwkViewResolver implements ViewResolver, Ordered {
private String jwkViewName = "jwkKeyList";
private View jwk;
private String x509ViewName = "x509certs";
private View x509;
private int order = HIGHEST_PRECEDENCE; // highest precedence, most specific -- avoids hitting the catch-all view resolvers
/**
* Map "jwkKeyList" to the jwk property and "x509certs" to the x509 property on this bean.
* Map "jwkKeyList" to the jwk property on this bean.
* Everything else returns null
*/
@Override
@ -35,8 +49,6 @@ public class JwkViewResolver implements ViewResolver, Ordered {
if (viewName != null) {
if (viewName.equals(getJwkViewName())) {
return getJwk();
} else if (viewName.equals(getX509ViewName())) {
return getX509();
} else {
return null;
}
@ -45,20 +57,6 @@ public class JwkViewResolver implements ViewResolver, Ordered {
}
}
/**
* @return the x509
*/
public View getX509() {
return x509;
}
/**
* @param x509 the x509 to set
*/
public void setX509(View x509) {
this.x509 = x509;
}
/**
* @return the jwk
*/
@ -102,18 +100,4 @@ public class JwkViewResolver implements ViewResolver, Ordered {
this.jwkViewName = jwkViewName;
}
/**
* @return the x509ViewName
*/
public String getX509ViewName() {
return x509ViewName;
}
/**
* @param x509ViewName the x509ViewName to set
*/
public void setX509ViewName(String x509ViewName) {
this.x509ViewName = x509ViewName;
}
}

View File

@ -1,3 +1,20 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.
******************************************************************************/
/**
*
*/

View File

@ -1,10 +1,27 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.service;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.config.ServerConfiguration;
import org.springframework.security.oauth2.provider.ClientDetails;
/**
* @author jricher
@ -20,6 +37,6 @@ public interface AuthRequestUrlBuilder {
* @param state
* @return
*/
public String buildAuthRequestUrl(ServerConfiguration serverConfig, ClientDetails clientConfig, String redirectUri, String nonce, String state);
public String buildAuthRequestUrl(ServerConfiguration serverConfig, RegisteredClient clientConfig, String redirectUri, String nonce, String state);
}

View File

@ -1,9 +1,27 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.service;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.config.ServerConfiguration;
/**
* @author jricher
@ -11,6 +29,6 @@ import org.springframework.security.oauth2.provider.ClientDetails;
*/
public interface ClientConfigurationService {
public ClientDetails getClientConfiguration(String issuer);
public RegisteredClient getClientConfiguration(ServerConfiguration issuer);
}

View File

@ -1,3 +1,20 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.
******************************************************************************/
/**
*
*/

View File

@ -0,0 +1,48 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.service;
import org.mitre.oauth2.model.RegisteredClient;
/**
* @author jricher
*
*/
public interface RegisteredClientService {
/**
* Get a remembered client (if one exists) to talk to the given issuer. This
* client likely doesn't have its full configuration information but contains
* the information needed to fetch it.
* @param issuer
* @return
*/
RegisteredClient getByIssuer(String issuer);
/**
* Save this client's information for talking to the given issuer. This will
* save only enough information to fetch the client's full configuration from
* the server.
* @param client
*/
void save(String issuer, RegisteredClient client);
}

View File

@ -1,3 +1,20 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.
******************************************************************************/
/**
*
*/

View File

@ -0,0 +1,208 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.service.impl;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.ClientDetailsEntityJsonProcessor;
import org.mitre.openid.connect.client.service.ClientConfigurationService;
import org.mitre.openid.connect.client.service.RegisteredClientService;
import org.mitre.openid.connect.config.ServerConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.web.client.RestTemplate;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Lists;
import com.google.gson.JsonObject;
/**
* @author jricher
*
*/
public class DynamicRegistrationClientConfigurationService implements ClientConfigurationService {
private static Logger logger = LoggerFactory.getLogger(DynamicServerConfigurationService.class);
private LoadingCache<ServerConfiguration, RegisteredClient> clients;
private RegisteredClientService registeredClientService = new InMemoryRegisteredClientService();
// TODO: make sure the template doesn't have "client_id", "client_secret", or "registration_access_token" set on it already
private RegisteredClient template;
private Set<String> whitelist = new HashSet<String>();
private Set<String> blacklist = new HashSet<String>();
public DynamicRegistrationClientConfigurationService() {
clients = CacheBuilder.newBuilder().build(new DynamicClientRegistrationLoader());
}
@Override
public RegisteredClient getClientConfiguration(ServerConfiguration issuer) {
try {
if (!whitelist.isEmpty() && !whitelist.contains(issuer)) {
throw new AuthenticationServiceException("Whitelist was nonempty, issuer was not in whitelist: " + issuer);
}
if (blacklist.contains(issuer)) {
throw new AuthenticationServiceException("Issuer was in blacklist: " + issuer);
}
return clients.get(issuer);
} catch (ExecutionException e) {
logger.warn("Unable to get client configuration", e);
return null;
}
}
/**
* @return the template
*/
public RegisteredClient getTemplate() {
return template;
}
/**
* @param template the template to set
*/
public void setTemplate(RegisteredClient template) {
this.template = template;
}
/**
* @return the registeredClientService
*/
public RegisteredClientService getRegisteredClientService() {
return registeredClientService;
}
/**
* @param registeredClientService the registeredClientService to set
*/
public void setRegisteredClientService(RegisteredClientService registeredClientService) {
this.registeredClientService = registeredClientService;
}
/**
* @return the whitelist
*/
public Set<String> getWhitelist() {
return whitelist;
}
/**
* @param whitelist the whitelist to set
*/
public void setWhitelist(Set<String> whitelist) {
this.whitelist = whitelist;
}
/**
* @return the blacklist
*/
public Set<String> getBlacklist() {
return blacklist;
}
/**
* @param blacklist the blacklist to set
*/
public void setBlacklist(Set<String> blacklist) {
this.blacklist = 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
*
*/
public class DynamicClientRegistrationLoader extends CacheLoader<ServerConfiguration, RegisteredClient> {
private HttpClient httpClient = new DefaultHttpClient();
private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
@Override
public RegisteredClient load(ServerConfiguration serverConfig) throws Exception {
RestTemplate restTemplate = new RestTemplate(httpFactory);
RegisteredClient knownClient = registeredClientService.getByIssuer(serverConfig.getIssuer());
if (knownClient == null) {
// dynamically register this client
JsonObject jsonRequest = ClientDetailsEntityJsonProcessor.serialize(template);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(Lists.newArrayList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>(jsonRequest.toString(), 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;
} else {
// load this client's information from the server
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", String.format("%s %s", OAuth2AccessToken.BEARER_TYPE, knownClient.getRegistrationAccessToken()));
headers.setAccept(Lists.newArrayList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>(headers);
String registered = restTemplate.exchange(knownClient.getRegistrationClientUri(), HttpMethod.GET, entity, String.class).getBody();
// TODO: handle HTTP errors
RegisteredClient client = ClientDetailsEntityJsonProcessor.parseRegistered(registered);
return client;
}
}
}
}

View File

@ -0,0 +1,180 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.service.impl;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.mitre.openid.connect.client.service.ServerConfigurationService;
import org.mitre.openid.connect.config.ServerConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.web.client.RestTemplate;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
/**
*
* Dynamically fetches OpenID Connect server configurations based on the issuer. Caches the server configurations.
*
* @author jricher
*
*/
public class DynamicServerConfigurationService implements ServerConfigurationService {
private static Logger logger = LoggerFactory.getLogger(DynamicServerConfigurationService.class);
// map of issuer -> server configuration, loaded dynamically from service discovery
private LoadingCache<String, ServerConfiguration> servers;
private Set<String> whitelist = new HashSet<String>();
private Set<String> blacklist = new HashSet<String>();
public DynamicServerConfigurationService() {
// initialize the cache
servers = CacheBuilder.newBuilder().build(new OpenIDConnectServiceConfigurationFetcher());
}
/**
* @return the whitelist
*/
public Set<String> getWhitelist() {
return whitelist;
}
/**
* @param whitelist the whitelist to set
*/
public void setWhitelist(Set<String> whitelist) {
this.whitelist = whitelist;
}
/**
* @return the blacklist
*/
public Set<String> getBlacklist() {
return blacklist;
}
/**
* @param blacklist the blacklist to set
*/
public void setBlacklist(Set<String> blacklist) {
this.blacklist = blacklist;
}
@Override
public ServerConfiguration getServerConfiguration(String issuer) {
try {
if (!whitelist.isEmpty() && !whitelist.contains(issuer)) {
throw new AuthenticationServiceException("Whitelist was nonempty, issuer was not in whitelist: " + issuer);
}
if (blacklist.contains(issuer)) {
throw new AuthenticationServiceException("Issuer was in blacklist: " + issuer);
}
return servers.get(issuer);
} catch (ExecutionException e) {
logger.warn("Couldn't load configuration for " + issuer, e);
return null;
}
}
/**
* @author jricher
*
*/
private class OpenIDConnectServiceConfigurationFetcher extends CacheLoader<String, ServerConfiguration> {
private HttpClient httpClient = new DefaultHttpClient();
private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
private JsonParser parser = new JsonParser();
@Override
public ServerConfiguration load(String issuer) throws Exception {
RestTemplate restTemplate = new RestTemplate(httpFactory);
// data holder
ServerConfiguration conf = new ServerConfiguration();
// construct the well-known URI
String url = issuer + "/.well-known/openid-configuration";
// fetch the value
String jsonString = restTemplate.getForObject(url, String.class);
JsonElement parsed = parser.parse(jsonString);
if (parsed.isJsonObject()) {
JsonObject o = parsed.getAsJsonObject();
// sanity checks
if (!o.has("issuer")) {
throw new IllegalStateException("Returned object did not have an 'issuer' field");
}
if (!issuer.equals(o.get("issuer").getAsString())) {
throw new IllegalStateException("Discovered issuers didn't match, expected " + issuer + " got " + o.get("issuer").getAsString());
}
conf.setIssuer(o.get("issuer").getAsString());
if (o.has("authorization_endpoint")) {
conf.setAuthorizationEndpointUri(o.get("authorization_endpoint").getAsString());
}
if (o.has("token_endpoint")) {
conf.setTokenEndpointUri(o.get("token_endpoint").getAsString());
}
if (o.has("jwks_uri")) {
conf.setJwksUri(o.get("jwks_uri").getAsString());
}
if (o.has("userinfo_endpoint")) {
conf.setUserInfoUri(o.get("userinfo_endpoint").getAsString());
}
if (o.has("registration_endpoint")) {
conf.setRegistrationEndpointUri(o.get("registration_endpoint").getAsString());
}
if (o.has("introspection_endpoint")) {
conf.setIntrospectionEndpointUri(o.get("introspection_endpoint").getAsString());
}
return conf;
} else {
throw new IllegalStateException("Couldn't parse server discovery results for " + url);
}
}
}
}

View File

@ -0,0 +1,143 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.service.impl;
import java.util.Map;
import java.util.Set;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.client.service.ClientConfigurationService;
import org.mitre.openid.connect.client.service.RegisteredClientService;
import org.mitre.openid.connect.config.ServerConfiguration;
/**
* Houses both a static client configuration and a dynamic client configuration
* service in one object. Checks the static service first, then falls through to
* the dynamic service.
*
* Provides configuration passthrough for the template, registered client service, whitelist,
* and blacklist for the dynamic service, and to the static service's client map.
*
* @author jricher
*
*/
public class HybridClientConfigurationService implements ClientConfigurationService {
private StaticClientConfigurationService staticClientService = new StaticClientConfigurationService();
private DynamicRegistrationClientConfigurationService dynamicClientService = new DynamicRegistrationClientConfigurationService();
/* (non-Javadoc)
* @see org.mitre.openid.connect.client.service.ClientConfigurationService#getClientConfiguration(org.mitre.openid.connect.config.ServerConfiguration)
*/
@Override
public RegisteredClient getClientConfiguration(ServerConfiguration issuer) {
RegisteredClient client = staticClientService.getClientConfiguration(issuer);
if (client != null) {
return client;
} else {
return dynamicClientService.getClientConfiguration(issuer);
}
}
/**
* @return
* @see org.mitre.openid.connect.client.service.impl.StaticClientConfigurationService#getClients()
*/
public Map<String, RegisteredClient> getClients() {
return staticClientService.getClients();
}
/**
* @param clients
* @see org.mitre.openid.connect.client.service.impl.StaticClientConfigurationService#setClients(java.util.Map)
*/
public void setClients(Map<String, RegisteredClient> clients) {
staticClientService.setClients(clients);
}
/**
* @return
* @see org.mitre.openid.connect.client.service.impl.DynamicRegistrationClientConfigurationService#getTemplate()
*/
public RegisteredClient getTemplate() {
return dynamicClientService.getTemplate();
}
/**
* @param template
* @see org.mitre.openid.connect.client.service.impl.DynamicRegistrationClientConfigurationService#setTemplate(org.mitre.oauth2.model.RegisteredClient)
*/
public void setTemplate(RegisteredClient template) {
dynamicClientService.setTemplate(template);
}
/**
* @return
* @see org.mitre.openid.connect.client.service.impl.DynamicRegistrationClientConfigurationService#getRegisteredClientService()
*/
public RegisteredClientService getRegisteredClientService() {
return dynamicClientService.getRegisteredClientService();
}
/**
* @param registeredClientService
* @see org.mitre.openid.connect.client.service.impl.DynamicRegistrationClientConfigurationService#setRegisteredClientService(org.mitre.openid.connect.client.service.RegisteredClientService)
*/
public void setRegisteredClientService(RegisteredClientService registeredClientService) {
dynamicClientService.setRegisteredClientService(registeredClientService);
}
/**
* @return
* @see org.mitre.openid.connect.client.service.impl.DynamicRegistrationClientConfigurationService#getWhitelist()
*/
public Set<String> getWhitelist() {
return dynamicClientService.getWhitelist();
}
/**
* @param whitelist
* @see org.mitre.openid.connect.client.service.impl.DynamicRegistrationClientConfigurationService#setWhitelist(java.util.Set)
*/
public void setWhitelist(Set<String> whitelist) {
dynamicClientService.setWhitelist(whitelist);
}
/**
* @return
* @see org.mitre.openid.connect.client.service.impl.DynamicRegistrationClientConfigurationService#getBlacklist()
*/
public Set<String> getBlacklist() {
return dynamicClientService.getBlacklist();
}
/**
* @param blacklist
* @see org.mitre.openid.connect.client.service.impl.DynamicRegistrationClientConfigurationService#setBlacklist(java.util.Set)
*/
public void setBlacklist(Set<String> blacklist) {
dynamicClientService.setBlacklist(blacklist);
}
}

View File

@ -0,0 +1,115 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.service.impl;
import java.util.Map;
import java.util.Set;
import org.mitre.openid.connect.client.service.ServerConfigurationService;
import org.mitre.openid.connect.config.ServerConfiguration;
/**
* Houses both a static server configuration and a dynamic server configuration
* service in one object. Checks the static service first, then falls through to
* the dynamic service.
*
* Provides configuration passthrough to the dynamic service's whitelist and blacklist,
* and to the static service's server map.
*
*
* @author jricher
*
*/
public class HybridServerConfigurationService implements ServerConfigurationService {
private StaticServerConfigurationService staticServerService;
private DynamicServerConfigurationService dynamicServerService;
/* (non-Javadoc)
* @see org.mitre.openid.connect.client.service.ServerConfigurationService#getServerConfiguration(java.lang.String)
*/
@Override
public ServerConfiguration getServerConfiguration(String issuer) {
ServerConfiguration server = staticServerService.getServerConfiguration(issuer);
if (server != null) {
return server;
} else {
return dynamicServerService.getServerConfiguration(issuer);
}
}
/**
* @return
* @see org.mitre.openid.connect.client.service.impl.StaticServerConfigurationService#getServers()
*/
public Map<String, ServerConfiguration> getServers() {
return staticServerService.getServers();
}
/**
* @param servers
* @see org.mitre.openid.connect.client.service.impl.StaticServerConfigurationService#setServers(java.util.Map)
*/
public void setServers(Map<String, ServerConfiguration> servers) {
staticServerService.setServers(servers);
}
/**
* @return
* @see org.mitre.openid.connect.client.service.impl.DynamicServerConfigurationService#getWhitelist()
*/
public Set<String> getWhitelist() {
return dynamicServerService.getWhitelist();
}
/**
* @param whitelist
* @see org.mitre.openid.connect.client.service.impl.DynamicServerConfigurationService#setWhitelist(java.util.Set)
*/
public void setWhitelist(Set<String> whitelist) {
dynamicServerService.setWhitelist(whitelist);
}
/**
* @return
* @see org.mitre.openid.connect.client.service.impl.DynamicServerConfigurationService#getBlacklist()
*/
public Set<String> getBlacklist() {
return dynamicServerService.getBlacklist();
}
/**
* @param blacklist
* @see org.mitre.openid.connect.client.service.impl.DynamicServerConfigurationService#setBlacklist(java.util.Set)
*/
public void setBlacklist(Set<String> blacklist) {
dynamicServerService.setBlacklist(blacklist);
}
}

View File

@ -0,0 +1,53 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.service.impl;
import java.util.HashMap;
import java.util.Map;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.client.service.RegisteredClientService;
/**
* @author jricher
*
*/
public class InMemoryRegisteredClientService implements RegisteredClientService {
private Map<String, RegisteredClient> clients = new HashMap<String, RegisteredClient>();
/* (non-Javadoc)
* @see org.mitre.openid.connect.client.service.RegisteredClientService#getByIssuer(java.lang.String)
*/
@Override
public RegisteredClient getByIssuer(String issuer) {
return clients.get(issuer);
}
/* (non-Javadoc)
* @see org.mitre.openid.connect.client.service.RegisteredClientService#save(org.mitre.oauth2.model.RegisteredClient)
*/
@Override
public void save(String issuer, RegisteredClient client) {
clients.put(issuer, client);
}
}

View File

@ -0,0 +1,166 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.service.impl;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.client.service.RegisteredClientService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.reflect.TypeToken;
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.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
/**
* @author jricher
*
*/
public class JsonFileRegisteredClientService implements RegisteredClientService {
private static Logger logger = LoggerFactory.getLogger(JsonFileRegisteredClientService.class);
private Gson gson = new GsonBuilder()
.registerTypeAdapter(RegisteredClient.class, new JsonSerializer<RegisteredClient>() {
@Override
public JsonElement serialize(RegisteredClient src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject obj = new JsonObject();
obj.addProperty("token", src.getRegistrationAccessToken());
obj.addProperty("uri", src.getRegistrationClientUri());
if (src.getClientIdIssuedAt() != null) {
obj.addProperty("issued", src.getClientIdIssuedAt().getTime());
}
if (src.getClientSecretExpiresAt() != null) {
obj.addProperty("expires", src.getClientSecretExpiresAt().getTime());
}
return obj;
}
})
.registerTypeAdapter(RegisteredClient.class, new JsonDeserializer<RegisteredClient>() {
@Override
public RegisteredClient deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (json.isJsonObject()) {
JsonObject src = json.getAsJsonObject();
RegisteredClient rc = new RegisteredClient();
rc.setRegistrationAccessToken(src.get("token").getAsString());
rc.setRegistrationClientUri(src.get("uri").getAsString());
if (src.has("issued") && !src.get("issued").isJsonNull()) {
rc.setClientIdIssuedAt(new Date(src.get("issued").getAsLong()));
}
if (src.has("expires") && !src.get("expires").isJsonNull()) {
rc.setClientSecretExpiresAt(new Date(src.get("expires").getAsLong()));
}
return rc;
} else {
return null;
}
}
})
.create();
private File file;
private Map<String, RegisteredClient> clients = new HashMap<String, RegisteredClient>();
public JsonFileRegisteredClientService(String filename) {
this.file = new File(filename);
load();
}
/* (non-Javadoc)
* @see org.mitre.openid.connect.client.service.RegisteredClientService#getByIssuer(java.lang.String)
*/
@Override
public RegisteredClient getByIssuer(String issuer) {
return clients.get(issuer);
}
/* (non-Javadoc)
* @see org.mitre.openid.connect.client.service.RegisteredClientService#save(java.lang.String, org.mitre.oauth2.model.RegisteredClient)
*/
@Override
public void save(String issuer, RegisteredClient client) {
clients.put(issuer, client);
write();
}
/**
* Sync the map of clients out to disk.
*/
private void write() {
try {
if (!file.exists()) {
// create a new file
logger.info("Creating saved clients list in " + file);
file.createNewFile();
}
FileWriter out = new FileWriter(file);
gson.toJson(clients, new TypeToken<Map<String, RegisteredClient>>(){}.getType(), out);
out.close();
} catch (FileNotFoundException e) {
logger.error("Could not write to output file", e);
} catch (IOException e) {
logger.error("Could not write to output file", e);
}
}
/**
* Load the map in from disk.
*/
private void load() {
try {
if (!file.exists()) {
logger.info("No sved clients file found in " + file);
return;
}
FileReader in = new FileReader(file);
clients = gson.fromJson(in, new TypeToken<Map<String, RegisteredClient>>(){}.getType());
in.close();
} catch (FileNotFoundException e) {
logger.error("Could not read from input file", e);
} catch (IOException e) {
logger.error("Could not read from input file", e);
}
}
}

View File

@ -1,3 +1,20 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.
******************************************************************************/
/**
*
*/
@ -6,10 +23,10 @@ package org.mitre.openid.connect.client.service.impl;
import java.net.URISyntaxException;
import org.apache.http.client.utils.URIBuilder;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.client.service.AuthRequestUrlBuilder;
import org.mitre.openid.connect.config.ServerConfiguration;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.oauth2.provider.ClientDetails;
import com.google.common.base.Joiner;
@ -26,7 +43,7 @@ public class PlainAuthRequestUrlBuilder implements AuthRequestUrlBuilder {
* @see org.mitre.openid.connect.client.service.AuthRequestUrlBuilder#buildAuthRequest(javax.servlet.http.HttpServletRequest, org.mitre.openid.connect.config.ServerConfiguration, org.springframework.security.oauth2.provider.ClientDetails)
*/
@Override
public String buildAuthRequestUrl(ServerConfiguration serverConfig, ClientDetails clientConfig, String redirectUri, String nonce, String state) {
public String buildAuthRequestUrl(ServerConfiguration serverConfig, RegisteredClient clientConfig, String redirectUri, String nonce, String state) {
try {
URIBuilder uriBuilder = new URIBuilder(serverConfig.getAuthorizationEndpointUri());

View File

@ -1,3 +1,20 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.
******************************************************************************/
/**
*
*/
@ -7,10 +24,10 @@ import java.net.URISyntaxException;
import org.apache.http.client.utils.URIBuilder;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.client.service.AuthRequestUrlBuilder;
import org.mitre.openid.connect.config.ServerConfiguration;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.oauth2.provider.ClientDetails;
import com.google.common.base.Joiner;
import com.nimbusds.jose.JWSHeader;
@ -29,7 +46,7 @@ public class SignedAuthRequestUrlBuilder implements AuthRequestUrlBuilder {
* @see org.mitre.openid.connect.client.service.AuthRequestUrlBuilder#buildAuthRequestUrl(org.mitre.openid.connect.config.ServerConfiguration, org.springframework.security.oauth2.provider.ClientDetails, java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public String buildAuthRequestUrl(ServerConfiguration serverConfig, ClientDetails clientConfig, String redirectUri, String nonce, String state) {
public String buildAuthRequestUrl(ServerConfiguration serverConfig, RegisteredClient clientConfig, String redirectUri, String nonce, String state) {
// create our signed JWT for the request object
JWTClaimsSet claims = new JWTClaimsSet();

View File

@ -1,3 +1,20 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.
******************************************************************************/
/**
*
*/
@ -5,9 +22,11 @@ package org.mitre.openid.connect.client.service.impl;
import java.util.Map;
import javax.annotation.PostConstruct;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.client.service.ClientConfigurationService;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.mitre.openid.connect.config.ServerConfiguration;
/**
* Client configuration service that holds a static map from issuer URL to a ClientDetails object to use at that issuer.
@ -17,22 +36,22 @@ import org.springframework.security.oauth2.provider.ClientDetails;
* @author jricher
*
*/
public class StaticClientConfigurationService implements ClientConfigurationService, InitializingBean {
public class StaticClientConfigurationService implements ClientConfigurationService {
// Map of issuer URL -> client configuration information
private Map<String, ClientDetails> clients;
private Map<String, RegisteredClient> clients;
/**
* @return the clients
*/
public Map<String, ClientDetails> getClients() {
public Map<String, RegisteredClient> getClients() {
return clients;
}
/**
* @param clients the clients to set
*/
public void setClients(Map<String, ClientDetails> clients) {
public void setClients(Map<String, RegisteredClient> clients) {
this.clients = clients;
}
@ -42,15 +61,12 @@ public class StaticClientConfigurationService implements ClientConfigurationServ
* @see org.mitre.openid.connect.client.service.ClientConfigurationService#getClientConfiguration(java.lang.String)
*/
@Override
public ClientDetails getClientConfiguration(String issuer) {
public RegisteredClient getClientConfiguration(ServerConfiguration issuer) {
return clients.get(issuer);
return clients.get(issuer.getIssuer());
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
@PostConstruct
public void afterPropertiesSet() throws Exception {
if (clients == null || clients.isEmpty()) {
throw new IllegalArgumentException("Clients map cannot be null or empty");

View File

@ -1,3 +1,20 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.
******************************************************************************/
/**
*
*/
@ -5,9 +22,10 @@ package org.mitre.openid.connect.client.service.impl;
import java.util.Map;
import javax.annotation.PostConstruct;
import org.mitre.openid.connect.client.service.ServerConfigurationService;
import org.mitre.openid.connect.config.ServerConfiguration;
import org.springframework.beans.factory.InitializingBean;
/**
* Statically configured server configuration service that maps issuer URLs to server configurations to use at that issuer.
@ -15,7 +33,7 @@ import org.springframework.beans.factory.InitializingBean;
* @author jricher
*
*/
public class StaticServerConfigurationService implements ServerConfigurationService, InitializingBean {
public class StaticServerConfigurationService implements ServerConfigurationService {
// map of issuer url -> server configuration information
private Map<String, ServerConfiguration> servers;
@ -42,10 +60,7 @@ public class StaticServerConfigurationService implements ServerConfigurationServ
return servers.get(issuer);
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
@PostConstruct
public void afterPropertiesSet() throws Exception {
if (servers == null || servers.isEmpty()) {
throw new IllegalArgumentException("Servers map cannot be null or empty.");

View File

@ -1,13 +1,30 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.service.impl;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import org.mitre.openid.connect.client.model.IssuerServiceResponse;
import org.mitre.openid.connect.client.service.IssuerService;
import org.springframework.beans.factory.InitializingBean;
import com.google.common.base.Strings;
@ -15,7 +32,7 @@ import com.google.common.base.Strings;
* @author jricher
*
*/
public class StaticSingleIssuerService implements IssuerService, InitializingBean {
public class StaticSingleIssuerService implements IssuerService {
private String issuer;
@ -43,10 +60,7 @@ public class StaticSingleIssuerService implements IssuerService, InitializingBea
return new IssuerServiceResponse(getIssuer(), null, null);
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
@PostConstruct
public void afterPropertiesSet() throws Exception {
if (Strings.isNullOrEmpty(issuer)) {

View File

@ -1,16 +1,35 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.service.impl;
import java.net.URISyntaxException;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import org.apache.http.client.utils.URIBuilder;
import org.mitre.openid.connect.client.model.IssuerServiceResponse;
import org.mitre.openid.connect.client.service.IssuerService;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.authentication.AuthenticationServiceException;
import com.google.common.base.Strings;
@ -22,10 +41,13 @@ import com.google.common.base.Strings;
* @author jricher
*
*/
public class ThirdPartyIssuerService implements IssuerService, InitializingBean {
public class ThirdPartyIssuerService implements IssuerService {
private String accountChooserUrl;
private Set<String> whitelist = new HashSet<String>();
private Set<String> blacklist = new HashSet<String>();
/* (non-Javadoc)
* @see org.mitre.openid.connect.client.service.IssuerService#getIssuer(javax.servlet.http.HttpServletRequest)
*/
@ -33,8 +55,17 @@ public class ThirdPartyIssuerService implements IssuerService, InitializingBean
public IssuerServiceResponse getIssuer(HttpServletRequest request) {
// if the issuer is passed in, return that
if (!Strings.isNullOrEmpty(request.getParameter("iss"))) {
return new IssuerServiceResponse(request.getParameter("iss"), request.getParameter("login_hint"), request.getParameter("target_link_uri"));
String iss = request.getParameter("iss");
if (!Strings.isNullOrEmpty(iss)) {
if (!whitelist.isEmpty() && !whitelist.contains(iss)) {
throw new AuthenticationServiceException("Whitelist was nonempty, issuer was not in whitelist: " + iss);
}
if (blacklist.contains(iss)) {
throw new AuthenticationServiceException("Issuer was in blacklist: " + iss);
}
return new IssuerServiceResponse(iss, request.getParameter("login_hint"), request.getParameter("target_link_uri"));
} else {
try {
@ -69,10 +100,38 @@ public class ThirdPartyIssuerService implements IssuerService, InitializingBean
this.accountChooserUrl = accountChooserUrl;
}
/**
* @return the whitelist
*/
public Set<String> getWhitelist() {
return whitelist;
}
/**
* @param whitelist the whitelist to set
*/
public void setWhitelist(Set<String> whitelist) {
this.whitelist = whitelist;
}
/**
* @return the blacklist
*/
public Set<String> getBlacklist() {
return blacklist;
}
/**
* @param blacklist the blacklist to set
*/
public void setBlacklist(Set<String> blacklist) {
this.blacklist = blacklist;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
@PostConstruct
public void afterPropertiesSet() throws Exception {
if (Strings.isNullOrEmpty(this.accountChooserUrl)) {
throw new IllegalArgumentException("Account Chooser URL cannot be null or empty");

View File

@ -0,0 +1,245 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.service.impl;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import javax.servlet.http.HttpServletRequest;
import org.apache.http.client.HttpClient;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.DefaultHttpClient;
import org.mitre.discovery.util.WebfingerURLNormalizer;
import org.mitre.openid.connect.client.model.IssuerServiceResponse;
import org.mitre.openid.connect.client.service.IssuerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponents;
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.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
/**
* Use Webfinger to discover the appropriate issuer for a user-given input string.
* @author jricher
*
*/
public class WebfingerIssuerService implements IssuerService {
private static Logger logger = LoggerFactory.getLogger(WebfingerIssuerService.class);
// map of user input -> issuer, loaded dynamically from webfinger discover
private LoadingCache<UriComponents, String> issuers;
private Set<String> whitelist = new HashSet<String>();
private Set<String> blacklist = new HashSet<String>();
/**
* Name of the incoming parameter to check for discovery purposes.
*/
private String parameterName = "identifier";
/**
* URL of the page to forward to if no identifier is given.
*/
private String loginPageUrl;
public WebfingerIssuerService() {
issuers = CacheBuilder.newBuilder().build(new WebfingerIssuerFetcher());
}
/* (non-Javadoc)
* @see org.mitre.openid.connect.client.service.IssuerService#getIssuer(javax.servlet.http.HttpServletRequest)
*/
@Override
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);
}
if (blacklist.contains(issuer)) {
throw new AuthenticationServiceException("Issuer was in blacklist: " + issuer);
}
return new IssuerServiceResponse(issuer, null, null);
} catch (ExecutionException e) {
logger.warn("Issue fetching issuer for user input: " + identifier, e);
return null;
}
} else {
logger.warn("No user input given, directing to login page: " + loginPageUrl);
return new IssuerServiceResponse(loginPageUrl);
}
}
/**
* @return the parameterName
*/
public String getParameterName() {
return parameterName;
}
/**
* @param parameterName the parameterName to set
*/
public void setParameterName(String parameterName) {
this.parameterName = parameterName;
}
/**
* @return the loginPageUrl
*/
public String getLoginPageUrl() {
return loginPageUrl;
}
/**
* @param loginPageUrl the loginPageUrl to set
*/
public void setLoginPageUrl(String loginPageUrl) {
this.loginPageUrl = loginPageUrl;
}
/**
* @return the whitelist
*/
public Set<String> getWhitelist() {
return whitelist;
}
/**
* @param whitelist the whitelist to set
*/
public void setWhitelist(Set<String> whitelist) {
this.whitelist = whitelist;
}
/**
* @return the blacklist
*/
public Set<String> getBlacklist() {
return blacklist;
}
/**
* @param blacklist the blacklist to set
*/
public void setBlacklist(Set<String> blacklist) {
this.blacklist = blacklist;
}
/**
* @author jricher
*
*/
private class WebfingerIssuerFetcher extends CacheLoader<UriComponents, String> {
private HttpClient httpClient = new DefaultHttpClient();
private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
private JsonParser parser = new JsonParser();
@Override
public String load(UriComponents key) throws Exception {
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();
if (!Strings.isNullOrEmpty(scheme) && scheme.equals("http")) {
scheme = "http://"; // add on colon and slashes.
logger.warn("Webfinger endpoint MUST use the https URI scheme.");
} else {
scheme = "https://";
}
// do a webfinger lookup
URIBuilder builder = new URIBuilder(scheme
+ key.getHost()
+ (key.getPort() >= 0 ? ":" + key.getPort() : "")
+ Strings.nullToEmpty(key.getPath())
+ "/.well-known/webfinger"
+ (Strings.isNullOrEmpty(key.getQuery()) ? "" : "?" + key.getQuery())
);
builder.addParameter("resource", key.toString());
builder.addParameter("rel", "http://openid.net/specs/connect/1.0/issuer");
// do the fetch
logger.info("Loading: " + builder.toString());
String webfingerResponse = restTemplate.getForObject(builder.build(), String.class);
// TODO: catch and handle HTTP errors
JsonElement json = parser.parse(webfingerResponse);
// TODO: catch and handle JSON errors
if (json != null && json.isJsonObject()) {
// find the issuer
JsonArray links = json.getAsJsonObject().get("links").getAsJsonArray();
for (JsonElement link : links) {
if (link.isJsonObject()) {
JsonObject linkObj = link.getAsJsonObject();
if (linkObj.has("href")
&& linkObj.has("rel")
&& linkObj.get("rel").getAsString().equals("http://openid.net/specs/connect/1.0/issuer")) {
// we found the issuer, return it
return linkObj.get("href").getAsString();
}
}
}
}
// we couldn't find it
if (key.getScheme().equals("http") || key.getScheme().equals("https")) {
// if it looks like HTTP then punt and return the input
logger.warn("Returning normalized input string as issuer, hoping for the best: " + key.toString());
return key.toString();
} else {
// if it's not HTTP, give up
logger.warn("Couldn't find issuer: " + key.toString());
return null;
}
}
}
}

View File

@ -0,0 +1,116 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.service.impl;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.config.ServerConfiguration;
import org.mockito.InjectMocks;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
/**
* @author wkim
*
*/
@RunWith(MockitoJUnitRunner.class)
public class TestHybridClientConfigurationService {
@Mock
private StaticClientConfigurationService mockStaticService;
@Mock
private DynamicRegistrationClientConfigurationService mockDynamicService;
@InjectMocks
private HybridClientConfigurationService hybridService;
// test fixture
@Mock
private RegisteredClient mockClient;
@Mock
private ServerConfiguration mockServerConfig;
private String issuer = "https://www.example.com/";
@Before
public void prepare() {
Mockito.reset(mockDynamicService, mockStaticService);
Mockito.when(mockServerConfig.getIssuer()).thenReturn(issuer);
}
@Test
public void getClientConfiguration_useStatic() {
Mockito.when(mockStaticService.getClientConfiguration(mockServerConfig)).thenReturn(mockClient);
RegisteredClient result = hybridService.getClientConfiguration(mockServerConfig);
Mockito.verify(mockStaticService).getClientConfiguration(mockServerConfig);
Mockito.verify(mockDynamicService, Mockito.never()).getClientConfiguration(Matchers.any(ServerConfiguration.class));
assertEquals(mockClient, result);
}
@Test
public void getClientConfiguration_useDynamic() {
Mockito.when(mockStaticService.getClientConfiguration(mockServerConfig)).thenReturn(null);
Mockito.when(mockDynamicService.getClientConfiguration(mockServerConfig)).thenReturn(mockClient);
RegisteredClient result = hybridService.getClientConfiguration(mockServerConfig);
Mockito.verify(mockStaticService).getClientConfiguration(mockServerConfig);
Mockito.verify(mockDynamicService).getClientConfiguration(mockServerConfig);
assertEquals(mockClient, result);
}
/**
* Checks the behavior when the issuer is not known.
*/
@Test
public void getClientConfiguration_noIssuer() {
// The mockServerConfig is known to both services
Mockito.when(mockStaticService.getClientConfiguration(mockServerConfig)).thenReturn(mockClient);
Mockito.when(mockDynamicService.getClientConfiguration(mockServerConfig)).thenReturn(mockClient);
// But oh noes! We're going to ask it to find us some other issuer
ServerConfiguration badIssuer = Mockito.mock(ServerConfiguration.class);
Mockito.when(badIssuer.getIssuer()).thenReturn("www.badexample.com");
RegisteredClient result = hybridService.getClientConfiguration(badIssuer);
Mockito.verify(mockStaticService).getClientConfiguration(badIssuer);
Mockito.verify(mockDynamicService).getClientConfiguration(badIssuer);
assertThat(result, is(nullValue()));
}
}

View File

@ -0,0 +1,107 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.service.impl;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mitre.openid.connect.config.ServerConfiguration;
import org.mockito.InjectMocks;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
/**
* @author wkim
*
*/
@RunWith(MockitoJUnitRunner.class)
public class TestHybridServerConfigurationService {
@Mock
private StaticServerConfigurationService mockStaticService;
@Mock
private DynamicServerConfigurationService mockDynamicService;
@InjectMocks
private HybridServerConfigurationService hybridService;
@Mock
private ServerConfiguration mockServerConfig;
private String issuer = "https://www.example.com/";
@Before
public void prepare() {
Mockito.reset(mockDynamicService, mockStaticService);
}
@Test
public void getServerConfiguration_useStatic() {
Mockito.when(mockStaticService.getServerConfiguration(issuer)).thenReturn(mockServerConfig);
ServerConfiguration result = hybridService.getServerConfiguration(issuer);
Mockito.verify(mockStaticService).getServerConfiguration(issuer);
Mockito.verify(mockDynamicService, Mockito.never()).getServerConfiguration(Matchers.anyString());
assertEquals(mockServerConfig, result);
}
@Test
public void getServerConfiguration_useDynamic() {
Mockito.when(mockStaticService.getServerConfiguration(issuer)).thenReturn(null);
Mockito.when(mockDynamicService.getServerConfiguration(issuer)).thenReturn(mockServerConfig);
ServerConfiguration result = hybridService.getServerConfiguration(issuer);
Mockito.verify(mockStaticService).getServerConfiguration(issuer);
Mockito.verify(mockDynamicService).getServerConfiguration(issuer);
assertEquals(mockServerConfig, result);
}
/**
* Checks the behavior when the issuer is not known.
*/
@Test
public void getServerConfiguration_noIssuer() {
Mockito.when(mockStaticService.getServerConfiguration(issuer)).thenReturn(mockServerConfig);
Mockito.when(mockDynamicService.getServerConfiguration(issuer)).thenReturn(mockServerConfig);
String badIssuer = "www.badexample.com";
ServerConfiguration result = hybridService.getServerConfiguration(badIssuer);
Mockito.verify(mockStaticService).getServerConfiguration(badIssuer);
Mockito.verify(mockDynamicService).getServerConfiguration(badIssuer);
assertThat(result, is(nullValue()));
}
}

View File

@ -0,0 +1,79 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.service.impl;
import org.junit.Before;
import org.junit.Test;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.config.ServerConfiguration;
import org.mockito.Mockito;
import org.springframework.security.authentication.AuthenticationServiceException;
import com.google.common.collect.Sets;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
/**
* @author wkim
*
*/
public class TestPlainAuthRequestUrlBuilder {
// Test fixture:
ServerConfiguration serverConfig;
RegisteredClient clientConfig;
private PlainAuthRequestUrlBuilder urlBuilder = new PlainAuthRequestUrlBuilder();
@Before
public void prepare() {
serverConfig = Mockito.mock(ServerConfiguration.class);
Mockito.when(serverConfig.getAuthorizationEndpointUri()).thenReturn("https://server.example.com/authorize");
clientConfig = Mockito.mock(RegisteredClient.class);
Mockito.when(clientConfig.getClientId()).thenReturn("s6BhdRkqt3");
Mockito.when(clientConfig.getScope()).thenReturn(Sets.newHashSet("openid", "profile"));
}
@Test
public void buildAuthRequestUrl() {
String expectedUrl = "https://server.example.com/authorize?" +
"response_type=code" +
"&client_id=s6BhdRkqt3" +
"&scope=openid+profile" + // plus sign used for space per application/x-www-form-encoded standard
"&redirect_uri=https%3A%2F%2Fclient.example.org%2F" +
"&nonce=34fasf3ds" +
"&state=af0ifjsldkj";
String actualUrl = urlBuilder.buildAuthRequestUrl(serverConfig, clientConfig, "https://client.example.org/", "34fasf3ds", "af0ifjsldkj");
assertThat(actualUrl, equalTo(expectedUrl));
}
@Test(expected = AuthenticationServiceException.class)
public void buildAuthRequestUrl_badUri() {
Mockito.when(serverConfig.getAuthorizationEndpointUri()).thenReturn("e=mc^2");
urlBuilder.buildAuthRequestUrl(serverConfig, clientConfig, "example.com", "", "");
}
}

View File

@ -0,0 +1,157 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.service.impl;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.text.ParseException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.mitre.jwt.signer.service.impl.DefaultJwtSigningAndValidationService;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.config.ServerConfiguration;
import org.mockito.Mockito;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.nimbusds.jose.Algorithm;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.Use;
import com.nimbusds.jose.util.Base64URL;
import com.nimbusds.jwt.ReadOnlyJWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* @author wkim
*
*/
public class TestSignedAuthRequestUrlBuilder {
// Test fixture:
private ServerConfiguration serverConfig;
private RegisteredClient clientConfig;
private String redirectUri = "https://client.example.org/";
private String nonce = "34fasf3ds";
private String state = "af0ifjsldkj";
private String responseType = "code";
// RSA key properties:
// {@link package com.nimbusds.jose.jwk#RSAKey}
private String n = "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zw" +
"u1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc" +
"5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8K" +
"JZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh" +
"6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw";
private String e = "AQAB";
private String d = "X4cTteJY_gn4FYPsXB8rdXix5vwsg1FLN5E3EaG6RJoVH-HLLKD9M7dx5oo7GURknc" +
"hnrRweUkC7hT5fJLM0WbFAKNLWY2vv7B6NqXSzUvxT0_YSfqijwp3RTzlBaCxWp4doFk5" +
"N2o8Gy_nHNKroADIkJ46pRUohsXywbReAdYaMwFs9tv8d_cPVY3i07a3t8MN6TNwm0dSa" +
"wm9v47UiCl3Sk5ZiG7xojPLu4sbg1U2jx4IBTNBznbJSzFHK66jT8bgkuqsk0GjskDJk1" +
"9Z4qwjwbsnn4j2WBii3RL-Us2lGVkY8fkFzme1z0HbIkfz0Y6mqnOYtqc0X4jfcKoAC8Q";
private String alg = "RS256";
private String kid = "2011-04-29";
private DefaultJwtSigningAndValidationService signingAndValidationService;
private SignedAuthRequestUrlBuilder urlBuilder = new SignedAuthRequestUrlBuilder();
@Before
public void prepare() throws NoSuchAlgorithmException, InvalidKeySpecException {
RSAKey key = new RSAKey(new Base64URL(n), new Base64URL(e), new Base64URL(d), Use.SIGNATURE, new Algorithm(alg), kid);
Map<String, JWK> keys = Maps.newHashMap();
keys.put("client", key);
signingAndValidationService = new DefaultJwtSigningAndValidationService(keys);
signingAndValidationService.setDefaultSignerKeyId("client");
signingAndValidationService.setDefaultSigningAlgorithmName(alg);
urlBuilder.setSigningAndValidationService(signingAndValidationService);
serverConfig = Mockito.mock(ServerConfiguration.class);
Mockito.when(serverConfig.getAuthorizationEndpointUri()).thenReturn("https://server.example.com/authorize");
clientConfig = Mockito.mock(RegisteredClient.class);
Mockito.when(clientConfig.getClientId()).thenReturn("s6BhdRkqt3");
Mockito.when(clientConfig.getScope()).thenReturn(Sets.newHashSet("openid", "profile"));
}
/**
* This test takes the URI from the result of building a signed request
* and checks that the JWS object parsed from the request URI matches up
* with the expected claim values.
*/
@Test
public void buildAuthRequestUrl() {
String requestUri = urlBuilder.buildAuthRequestUrl(serverConfig, clientConfig, redirectUri, nonce, state);
// parsing the result
UriComponentsBuilder builder = null;
try {
builder = UriComponentsBuilder.fromUri(new URI(requestUri));
} catch (URISyntaxException e1) {
fail("URISyntaxException was thrown.");
}
UriComponents components = builder.build();
String jwtString = components.getQueryParams().get("request").get(0);
ReadOnlyJWTClaimsSet claims = null;
try {
SignedJWT jwt = SignedJWT.parse(jwtString);
claims = jwt.getJWTClaimsSet();
} catch (ParseException e) {
fail("ParseException was thrown.");
}
assertEquals(responseType, claims.getClaim("response_type"));
assertEquals(clientConfig.getClientId(), claims.getClaim("client_id"));
List<String> scopeList = Arrays.asList(((String) claims.getClaim("scope")).split(" "));
assertTrue(scopeList.containsAll(clientConfig.getScope()));
assertEquals(redirectUri, claims.getClaim("redirect_uri"));
assertEquals(nonce, claims.getClaim("nonce"));
assertEquals(state, claims.getClaim("state"));
}
@Test(expected = AuthenticationServiceException.class)
public void buildAuthRequestUrl_badUri() {
Mockito.when(serverConfig.getAuthorizationEndpointUri()).thenReturn("e=mc^2");
urlBuilder.buildAuthRequestUrl(serverConfig, clientConfig, "example.com", "", "");
}
}

View File

@ -0,0 +1,89 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.service.impl;
import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.config.ServerConfiguration;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
/**
* @author wkim
*
*/
@RunWith(MockitoJUnitRunner.class)
public class TestStaticClientConfigurationService {
private StaticClientConfigurationService service;
private String issuer = "https://www.example.com/";
@Mock
private RegisteredClient mockClient;
@Mock
private ServerConfiguration mockServerConfig;
@Before
public void prepare() {
service = new StaticClientConfigurationService();
Map<String, RegisteredClient> clients = new HashMap<String, RegisteredClient>();
clients.put(issuer, mockClient);
service.setClients(clients);
Mockito.when(mockServerConfig.getIssuer()).thenReturn(issuer);
}
@Test
public void getClientConfiguration_success() {
RegisteredClient result = service.getClientConfiguration(mockServerConfig);
assertThat(mockClient, is(notNullValue()));
assertEquals(mockClient, result);
}
/**
* Checks the behavior when the issuer is not known.
*/
@Test
public void getClientConfiguration_noIssuer() {
Mockito.when(mockServerConfig.getIssuer()).thenReturn("www.badexample.net");
RegisteredClient actualClient = service.getClientConfiguration(mockServerConfig);
assertThat(actualClient, is(nullValue()));
}
}

View File

@ -0,0 +1,82 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.service.impl;
import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mitre.openid.connect.config.ServerConfiguration;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
/**
* @author wkim
*
*/
@RunWith(MockitoJUnitRunner.class)
public class TestStaticServerConfigurationService {
private StaticServerConfigurationService service;
private String issuer = "https://www.example.com/";
@Mock
private ServerConfiguration mockServerConfig;
@Before
public void prepare() {
service = new StaticServerConfigurationService();
Map<String, ServerConfiguration> servers = new HashMap<String, ServerConfiguration>();
servers.put(issuer, mockServerConfig);
service.setServers(servers);
}
@Test
public void getServerConfiguration_success() {
ServerConfiguration result = service.getServerConfiguration(issuer);
assertThat(mockServerConfig, is(notNullValue()));
assertEquals(mockServerConfig, result);
}
/**
* Checks the behavior when the issuer is not known.
*/
@Test
public void getClientConfiguration_noIssuer() {
ServerConfiguration result = service.getServerConfiguration("www.badexample.net");
assertThat(result, is(nullValue()));
}
}

View File

@ -0,0 +1,129 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.service.impl;
import javax.servlet.http.HttpServletRequest;
import org.junit.Before;
import org.junit.Test;
import org.mitre.openid.connect.client.model.IssuerServiceResponse;
import org.mockito.Mockito;
import org.springframework.security.authentication.AuthenticationServiceException;
import com.google.common.collect.Sets;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
/**
* @author wkim
*
*/
public class TestThirdPartyIssuerService {
// Test fixture:
private HttpServletRequest request;
private String iss = "https://server.example.org";
private String login_hint = "I'm not telling you nothin!";
private String target_link_uri = "https://www.example.com";
private String redirect_uri = "https://www.example.com";
private String accountChooserUrl = "https://www.example.com/account";
private ThirdPartyIssuerService service = new ThirdPartyIssuerService();
@Before
public void prepare() {
service.setAccountChooserUrl(accountChooserUrl);
request = Mockito.mock(HttpServletRequest.class);
Mockito.when(request.getParameter("iss")).thenReturn(iss);
Mockito.when(request.getParameter("login_hint")).thenReturn(login_hint);
Mockito.when(request.getParameter("target_link_uri")).thenReturn(target_link_uri);
Mockito.when(request.getRequestURL()).thenReturn(new StringBuffer(redirect_uri));
}
@Test
public void getIssuer_hasIssuer() {
IssuerServiceResponse response = service.getIssuer(request);
assertThat(response.getIssuer(), equalTo(iss));
assertThat(response.getLoginHint(), equalTo(login_hint));
assertThat(response.getTargetLinkUri(), equalTo(target_link_uri));
assertThat(response.getRedirectUrl(), nullValue());
}
@Test
public void getIssuer_noIssuer() {
Mockito.when(request.getParameter("iss")).thenReturn(null);
IssuerServiceResponse response = service.getIssuer(request);
assertThat(response.getIssuer(), nullValue());
assertThat(response.getLoginHint(), nullValue());
assertThat(response.getTargetLinkUri(), nullValue());
String expectedRedirectUrl = accountChooserUrl + "?redirect_uri=" + "https%3A%2F%2Fwww.example.com"; // url-encoded string of the request url
assertThat(response.getRedirectUrl(), equalTo(expectedRedirectUrl));
}
@Test
public void getIssuer_isWhitelisted() {
service.setWhitelist(Sets.newHashSet(iss));
IssuerServiceResponse response = service.getIssuer(request);
assertThat(response.getIssuer(), equalTo(iss));
assertThat(response.getLoginHint(), equalTo(login_hint));
assertThat(response.getTargetLinkUri(), equalTo(target_link_uri));
assertThat(response.getRedirectUrl(), nullValue());
}
@Test(expected = AuthenticationServiceException.class)
public void getIssuer_notWhitelisted() {
service.setWhitelist(Sets.newHashSet("some.other.site"));
service.getIssuer(request);
}
@Test(expected = AuthenticationServiceException.class)
public void getIssuer_blacklisted() {
service.setBlacklist(Sets.newHashSet(iss));
service.getIssuer(request);
}
@Test(expected = AuthenticationServiceException.class)
public void getIssuer_badUri() {
Mockito.when(request.getParameter("iss")).thenReturn(null);
service.setAccountChooserUrl("e=mc^2");
service.getIssuer(request);
}
}

View File

@ -1,4 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2013 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.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jwt-signer="http://www.mitre.org/schema/openid-connect/jwt-signer"
@ -37,4 +53,4 @@
</property>
</bean>
</beans>
</beans>

View File

@ -1,6 +1,20 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!--
Copyright 2013 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
@ -8,18 +22,12 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
<groupId>org.mitre</groupId>
<version>1.1.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.mitre</groupId>
</parent>
<artifactId>openid-connect-common</artifactId>
<version>1.1.0-SNAPSHOT</version>
<description>OpenID Connect Common modules</description>
<name>OpenID Connect Common</name>
<dependencies>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<version>1.1.0.M1</version>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
</dependencies>
<packaging>jar</packaging>
<build>
@ -36,7 +44,6 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<id>attach-sources</id>
@ -50,7 +57,6 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>attach-sources</id>

View File

@ -0,0 +1,184 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.discovery.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import com.google.common.base.Strings;
/**
* Provides utility methods for normalizing and parsing URIs for use with Webfinger Discovery.
*
* @author wkim
*
*/
public class WebfingerURLNormalizer {
private static Logger logger = LoggerFactory.getLogger(WebfingerURLNormalizer.class);
// pattern used to parse user input; we can't use the built-in java URI parser
private static final Pattern pattern = Pattern.compile("^" +
"((https|acct|http|mailto|tel|device):(//)?)?" + // scheme
"(" +
"(([^@]+)@)?" + // userinfo
"(([^\\?#:/]+)" + // host
"(:(\\d*))?)" + // port
")" +
"([^\\?#]+)?" + // path
"(\\?([^#]+))?" + // query
"(#(.*))?" + // fragment
"$"
);
/**
* Private constructor to prevent instantiation.
*/
private WebfingerURLNormalizer() {
// intentionally blank
}
/**
* Normalize the resource string as per OIDC Discovery.
* @param identifier
* @return the normalized string, or null if the string can't be normalized
*/
public static UriComponents normalizeResource(String identifier) {
// try to parse the URI
// NOTE: we can't use the Java built-in URI class because it doesn't split the parts appropriately
if (Strings.isNullOrEmpty(identifier)) {
logger.warn("Can't normalize null or empty URI: " + identifier);
return null; // nothing we can do
} else {
//UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(identifier);
UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
Matcher m = pattern.matcher(identifier);
if (m.matches()) {
builder.scheme(m.group(2));
builder.userInfo(m.group(6));
builder.host(m.group(8));
String port = m.group(10);
if (!Strings.isNullOrEmpty(port)) {
builder.port(Integer.parseInt(port));
}
builder.path(m.group(11));
builder.query(m.group(13));
builder.fragment(m.group(15)); // we throw away the hash, but this is the group it would be if we kept it
} else {
// doesn't match the pattern, throw it out
logger.warn("Parser couldn't match input: " + identifier);
return null;
}
UriComponents n = builder.build();
if (Strings.isNullOrEmpty(n.getScheme())) {
if (!Strings.isNullOrEmpty(n.getUserInfo())
&& Strings.isNullOrEmpty(n.getPath())
&& Strings.isNullOrEmpty(n.getQuery())
&& n.getPort() < 0) {
// scheme empty, userinfo is not empty, path/query/port are empty
// set to "acct" (rule 2)
builder.scheme("acct");
} else {
// scheme is empty, but rule 2 doesn't apply
// set scheme to "https" (rule 3)
builder.scheme("https");
}
}
// fragment must be stripped (rule 4)
builder.fragment(null);
return builder.build();
}
}
public static String serializeURL(UriComponents uri) {
if (uri.getScheme() != null &&
(uri.getScheme().equals("acct") ||
uri.getScheme().equals("mailto") ||
uri.getScheme().equals("tel") ||
uri.getScheme().equals("device")
)) {
// serializer copied from HierarchicalUriComponents but with "//" removed
StringBuilder uriBuilder = new StringBuilder();
if (uri.getScheme() != null) {
uriBuilder.append(uri.getScheme());
uriBuilder.append(':');
}
if (uri.getUserInfo() != null || uri.getHost() != null) {
if (uri.getUserInfo() != null) {
uriBuilder.append(uri.getUserInfo());
uriBuilder.append('@');
}
if (uri.getHost() != null) {
uriBuilder.append(uri.getHost());
}
if (uri.getPort() != -1) {
uriBuilder.append(':');
uriBuilder.append(uri.getPort());
}
}
String path = uri.getPath();
if (StringUtils.hasLength(path)) {
if (uriBuilder.length() != 0 && path.charAt(0) != '/') {
uriBuilder.append('/');
}
uriBuilder.append(path);
}
String query = uri.getQuery();
if (query != null) {
uriBuilder.append('?');
uriBuilder.append(query);
}
if (uri.getFragment() != null) {
uriBuilder.append('#');
uriBuilder.append(uri.getFragment());
}
return uriBuilder.toString();
} else {
return uri.toUriString();
}
}
}

View File

@ -1,3 +1,18 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.
******************************************************************************/
/**
*
*/

View File

@ -1,3 +1,18 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.
******************************************************************************/
/**
*
*/

View File

@ -1,3 +1,18 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.
******************************************************************************/
/**
*
*/

View File

@ -1,3 +1,18 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.
******************************************************************************/
/**
*
*/
@ -6,7 +21,8 @@ package org.mitre.jose.keystore;
import java.io.InputStreamReader;
import java.util.List;
import org.springframework.beans.factory.InitializingBean;
import javax.annotation.PostConstruct;
import org.springframework.core.io.Resource;
import com.google.common.base.Charsets;
@ -18,7 +34,7 @@ import com.nimbusds.jose.jwk.JWKSet;
* @author jricher
*
*/
public class JWKSetKeyStore implements InitializingBean {
public class JWKSetKeyStore {
private JWKSet jwkSet;
@ -32,10 +48,7 @@ public class JWKSetKeyStore implements InitializingBean {
this.jwkSet = jwkSet;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
@PostConstruct
public void afterPropertiesSet() throws Exception {
if (jwkSet == null) {

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,6 +16,7 @@
package org.mitre.jwt.signer.service;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
import java.util.Map;
import com.nimbusds.jose.JWSAlgorithm;
@ -56,6 +57,12 @@ public interface JwtSigningAndValidationService {
*/
public JWSAlgorithm getDefaultSigningAlgorithm();
/**
* Get the list of all signing algorithms supported by this service.
* @return
*/
public Collection<JWSAlgorithm> getAllSigningAlgsSupported();
/**
* 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.

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,14 +17,18 @@ package org.mitre.jwt.signer.service.impl;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.annotation.PostConstruct;
import org.mitre.jose.keystore.JWKSetKeyStore;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import com.google.common.base.Strings;
import com.nimbusds.jose.JOSEException;
@ -41,7 +45,7 @@ import com.nimbusds.jose.jwk.OctetSequenceKey;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jwt.SignedJWT;
public class DefaultJwtSigningAndValidationService implements JwtSigningAndValidationService, InitializingBean {
public class DefaultJwtSigningAndValidationService implements JwtSigningAndValidationService {
// map of identifier to signer
private Map<String, JWSSigner> signers = new HashMap<String, JWSSigner>();
@ -99,6 +103,18 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
buildSignersAndVerifiers();
}
@PostConstruct
public void afterPropertiesSet() throws NoSuchAlgorithmException, InvalidKeySpecException{
if (keys == null) {
throw new IllegalArgumentException("Signing and validation service must have at least one key configured.");
}
buildSignersAndVerifiers();
logger.info("DefaultJwtSigningAndValidationService is ready: " + this.toString());
}
/**
* @return the defaultSignerKeyId
*/
@ -133,24 +149,6 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
}
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() throws NoSuchAlgorithmException, InvalidKeySpecException{
if (keys == null) {
throw new IllegalArgumentException("Signing and validation service must have at least one key configured.");
}
buildSignersAndVerifiers();
logger.info("DefaultJwtSigningAndValidationService is ready: " + this.toString());
}
/**
* Build all of the signers and verifiers for this based on the key map.
* @throws InvalidKeySpecException If the keys in the JWKs are not valid
@ -210,8 +208,8 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
try {
jwt.sign(signer);
} catch (JOSEException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error("Failed to sign JWT, error was: ", e);
}
}
@ -225,8 +223,8 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
return true;
}
} catch (JOSEException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error("Failed to validate signature, error was: ", e);
}
}
return false;
@ -248,4 +246,23 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
return pubKeys;
}
/* (non-Javadoc)
* @see org.mitre.jwt.signer.service.JwtSigningAndValidationService#getAllSigningAlgsSupported()
*/
@Override
public Collection<JWSAlgorithm> getAllSigningAlgsSupported() {
Set<JWSAlgorithm> algs = new HashSet<JWSAlgorithm>();
for (JWSSigner signer : signers.values()) {
algs.addAll(signer.supportedAlgorithms());
}
for (JWSVerifier verifier : verifiers.values()) {
algs.addAll(verifier.supportedAlgorithms());
}
return algs;
}
}

View File

@ -1,3 +1,18 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.
******************************************************************************/
/**
*
*/
@ -9,18 +24,21 @@ import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.mitre.jose.keystore.JWKSetKeyStore;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.nimbusds.jose.jwk.JWKSet;
/**
*
* Creates a
* Creates a caching map of JOSE signers and validators keyed on the JWK Set URI.
* Dynamically loads JWK Sets to create the signing and validation services.
*
* @author jricher
*
@ -28,7 +46,10 @@ import com.nimbusds.jose.jwk.JWKSet;
@Service
public class JWKSetSigningAndValidationServiceCacheService {
private Cache<String, JwtSigningAndValidationService> cache;
private static Logger logger = LoggerFactory.getLogger(JWKSetSigningAndValidationServiceCacheService.class);
// map of jwk set uri -> signing/validation service built on the keys found in that jwk set
private LoadingCache<String, JwtSigningAndValidationService> cache;
public JWKSetSigningAndValidationServiceCacheService() {
this.cache = CacheBuilder.newBuilder()
@ -37,17 +58,16 @@ public class JWKSetSigningAndValidationServiceCacheService {
}
/**
* @param key
* @param jwksUri
* @return
* @throws ExecutionException
* @see com.google.common.cache.Cache#get(java.lang.Object)
*/
public JwtSigningAndValidationService get(String key) {
public JwtSigningAndValidationService get(String jwksUri) {
try {
return cache.get(key);
return cache.get(jwksUri);
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.warn("Couldn't load JWK Set from " + jwksUri, e);
return null;
}
}

View File

@ -1,3 +1,18 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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;
import javax.persistence.Basic;
@ -15,7 +30,7 @@ import javax.persistence.Table;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
@Entity
@Table(name="authentication_holder")
@Table(name = "authentication_holder")
@NamedQueries ({
@NamedQuery(name = "AuthenticationHolderEntity.getByAuthentication", query = "select a from AuthenticationHolderEntity a where a.authentication = :authentication")
})
@ -33,6 +48,7 @@ public class AuthenticationHolderEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
public Long getId() {
return id;
}
@ -42,7 +58,7 @@ public class AuthenticationHolderEntity {
}
@Basic
@Column(name="owner_id")
@Column(name = "owner_id")
public Long getOwnerId() {
return ownerId;
}
@ -53,6 +69,7 @@ public class AuthenticationHolderEntity {
@Lob
@Basic(fetch=FetchType.LAZY)
@Column(name = "authentication")
public OAuth2Authentication getAuthentication() {
return authentication;
}

View File

@ -1,3 +1,18 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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;
import javax.persistence.Basic;
@ -21,7 +36,7 @@ import org.springframework.security.oauth2.provider.OAuth2Authentication;
*
*/
@Entity
@Table(name="authorization_code")
@Table(name = "authorization_code")
@NamedQueries({
@NamedQuery(name = "AuthorizationCodeEntity.getByValue", query = "select a from AuthorizationCodeEntity a where a.code = :code")
})
@ -56,6 +71,7 @@ public class AuthorizationCodeEntity {
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
public Long getId() {
return id;
}
@ -71,6 +87,7 @@ public class AuthorizationCodeEntity {
* @return the code
*/
@Basic
@Column(name = "code")
public String getCode() {
return code;
}

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -57,7 +57,7 @@ import org.springframework.security.oauth2.provider.ClientDetails;
*
*/
@Entity
@Table(name="client_details")
@Table(name = "client_details")
@NamedQueries({
@NamedQuery(name = "ClientDetailsEntity.findAll", query = "SELECT c FROM ClientDetailsEntity c"),
@NamedQuery(name = "ClientDetailsEntity.getByClientId", query = "select c from ClientDetailsEntity c where c.clientId = :clientId")
@ -217,6 +217,7 @@ public class ClientDetailsEntity implements ClientDetails {
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
public Long getId() {
return id;
}
@ -774,7 +775,7 @@ public class ClientDetailsEntity implements ClientDetails {
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(
name="client_response_type",
joinColumns=@JoinColumn(name="response_type")
joinColumns=@JoinColumn(name="owner_id")
)
@Column(name="response_type")
public Set<String> getResponseTypes() {

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -54,8 +54,9 @@ import com.nimbusds.jwt.JWTParser;
*
*/
@Entity
@Table(name="access_token")
@Table(name = "access_token")
@NamedQueries({
@NamedQuery(name = "OAuth2AccessTokenEntity.getAll", query = "select a from OAuth2AccessTokenEntity a"),
@NamedQuery(name = "OAuth2AccessTokenEntity.getByRefreshToken", query = "select a from OAuth2AccessTokenEntity a where a.refreshToken = :refreshToken"),
@NamedQuery(name = "OAuth2AccessTokenEntity.getByClient", query = "select a from OAuth2AccessTokenEntity a where a.client = :client"),
@NamedQuery(name = "OAuth2AccessTokenEntity.getExpired", query = "select a from OAuth2AccessTokenEntity a where a.expiration is not null and a.expiration < current_timestamp"),
@ -102,6 +103,7 @@ public class OAuth2AccessTokenEntity implements OAuth2AccessToken {
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
public Long getId() {
return id;
}
@ -182,6 +184,7 @@ public class OAuth2AccessTokenEntity implements OAuth2AccessToken {
@Override
@Basic
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
@Column(name = "expiration")
public Date getExpiration() {
return expiration;
}
@ -214,7 +217,6 @@ public class OAuth2AccessTokenEntity implements OAuth2AccessToken {
public void setRefreshToken(OAuth2RefreshToken refreshToken) {
if (!(refreshToken instanceof OAuth2RefreshTokenEntity)) {
// TODO: make a copy constructor instead....
throw new IllegalArgumentException("Not a storable refresh token entity!");
}
// force a pass through to the entity version
@ -285,10 +287,19 @@ public class OAuth2AccessTokenEntity implements OAuth2AccessToken {
}
@Override
@Transient
public int getExpiresIn() {
// TODO Auto-generated method stub
return 0;
if (getExpiration() == null) {
return -1; // no expiration time
} else {
int secondsRemaining = (int) ((getExpiration().getTime() - System.currentTimeMillis()) / 1000);
if (isExpired()) {
return 0; // has an expiration time and expired
} else { // has an expiration time and not expired
return secondsRemaining;
}
}
}
}

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -46,8 +46,9 @@ import com.nimbusds.jwt.JWTParser;
*
*/
@Entity
@Table(name="refresh_token")
@Table(name = "refresh_token")
@NamedQueries({
@NamedQuery(name = "OAuth2RefreshTokenEntity.getAll", query = "select r from OAuth2RefreshTokenEntity r"),
@NamedQuery(name = "OAuth2RefreshTokenEntity.getByClient", query = "select r from OAuth2RefreshTokenEntity r where r.client = :client"),
@NamedQuery(name = "OAuth2RefreshTokenEntity.getExpired", query = "select r from OAuth2RefreshTokenEntity r where r.expiration is not null and r.expiration < current_timestamp"),
@NamedQuery(name = "OAuth2RefreshTokenEntity.getByTokenValue", query = "select r from OAuth2RefreshTokenEntity r where r.value = :tokenValue"),
@ -79,6 +80,7 @@ public class OAuth2RefreshTokenEntity implements OAuth2RefreshToken {
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
public Long getId() {
return id;
}
@ -130,6 +132,7 @@ public class OAuth2RefreshTokenEntity implements OAuth2RefreshToken {
@Basic
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
@Column(name = "expiration")
public Date getExpiration() {
return expiration;
}

View File

@ -0,0 +1,736 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import org.mitre.jose.JWEAlgorithmEmbed;
import org.mitre.jose.JWEEncryptionMethodEmbed;
import org.mitre.jose.JWSAlgorithmEmbed;
import org.mitre.oauth2.model.ClientDetailsEntity.AppType;
import org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod;
import org.mitre.oauth2.model.ClientDetailsEntity.SubjectType;
import org.springframework.security.core.GrantedAuthority;
/**
* @author jricher
*
*/
public class RegisteredClient {
// these fields are needed in addition to the ones in ClientDetailsEntity
private String registrationAccessToken;
private String registrationClientUri;
private Date clientSecretExpiresAt;
private Date clientIdIssuedAt;
private ClientDetailsEntity client;
/**
*
*/
public RegisteredClient() {
this.client = new ClientDetailsEntity();
}
/**
* @param client
*/
public RegisteredClient(ClientDetailsEntity client) {
this.client = client;
}
/**
* @param client
* @param registrationAccessToken
* @param registrationClientUri
*/
public RegisteredClient(ClientDetailsEntity client, String registrationAccessToken, String registrationClientUri) {
this.client = client;
this.registrationAccessToken = registrationAccessToken;
this.registrationClientUri = registrationClientUri;
}
/**
* @return the client
*/
public ClientDetailsEntity getClient() {
return client;
}
/**
* @param client the client to set
*/
public void setClient(ClientDetailsEntity client) {
this.client = client;
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getClientDescription()
*/
public String getClientDescription() {
return client.getClientDescription();
}
/**
* @param clientDescription
* @see org.mitre.oauth2.model.ClientDetailsEntity#setClientDescription(java.lang.String)
*/
public void setClientDescription(String clientDescription) {
client.setClientDescription(clientDescription);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#isAllowRefresh()
*/
public boolean isAllowRefresh() {
return client.isAllowRefresh();
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#isReuseRefreshToken()
*/
public boolean isReuseRefreshToken() {
return client.isReuseRefreshToken();
}
/**
* @param reuseRefreshToken
* @see org.mitre.oauth2.model.ClientDetailsEntity#setReuseRefreshToken(boolean)
*/
public void setReuseRefreshToken(boolean reuseRefreshToken) {
client.setReuseRefreshToken(reuseRefreshToken);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getIdTokenValiditySeconds()
*/
public Integer getIdTokenValiditySeconds() {
return client.getIdTokenValiditySeconds();
}
/**
* @param idTokenValiditySeconds
* @see org.mitre.oauth2.model.ClientDetailsEntity#setIdTokenValiditySeconds(java.lang.Integer)
*/
public void setIdTokenValiditySeconds(Integer idTokenValiditySeconds) {
client.setIdTokenValiditySeconds(idTokenValiditySeconds);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#isDynamicallyRegistered()
*/
public boolean isDynamicallyRegistered() {
return client.isDynamicallyRegistered();
}
/**
* @param dynamicallyRegistered
* @see org.mitre.oauth2.model.ClientDetailsEntity#setDynamicallyRegistered(boolean)
*/
public void setDynamicallyRegistered(boolean dynamicallyRegistered) {
client.setDynamicallyRegistered(dynamicallyRegistered);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#isAllowIntrospection()
*/
public boolean isAllowIntrospection() {
return client.isAllowIntrospection();
}
/**
* @param allowIntrospection
* @see org.mitre.oauth2.model.ClientDetailsEntity#setAllowIntrospection(boolean)
*/
public void setAllowIntrospection(boolean allowIntrospection) {
client.setAllowIntrospection(allowIntrospection);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#isSecretRequired()
*/
public boolean isSecretRequired() {
return client.isSecretRequired();
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#isScoped()
*/
public boolean isScoped() {
return client.isScoped();
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getClientId()
*/
public String getClientId() {
return client.getClientId();
}
/**
* @param clientId
* @see org.mitre.oauth2.model.ClientDetailsEntity#setClientId(java.lang.String)
*/
public void setClientId(String clientId) {
client.setClientId(clientId);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getClientSecret()
*/
public String getClientSecret() {
return client.getClientSecret();
}
/**
* @param clientSecret
* @see org.mitre.oauth2.model.ClientDetailsEntity#setClientSecret(java.lang.String)
*/
public void setClientSecret(String clientSecret) {
client.setClientSecret(clientSecret);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getScope()
*/
public Set<String> getScope() {
return client.getScope();
}
/**
* @param scope
* @see org.mitre.oauth2.model.ClientDetailsEntity#setScope(java.util.Set)
*/
public void setScope(Set<String> scope) {
client.setScope(scope);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getGrantTypes()
*/
public Set<String> getGrantTypes() {
return client.getGrantTypes();
}
/**
* @param grantTypes
* @see org.mitre.oauth2.model.ClientDetailsEntity#setGrantTypes(java.util.Set)
*/
public void setGrantTypes(Set<String> grantTypes) {
client.setGrantTypes(grantTypes);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getAuthorizedGrantTypes()
*/
public Set<String> getAuthorizedGrantTypes() {
return client.getAuthorizedGrantTypes();
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getAuthorities()
*/
public Set<GrantedAuthority> getAuthorities() {
return client.getAuthorities();
}
/**
* @param authorities
* @see org.mitre.oauth2.model.ClientDetailsEntity#setAuthorities(java.util.Set)
*/
public void setAuthorities(Set<GrantedAuthority> authorities) {
client.setAuthorities(authorities);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getAccessTokenValiditySeconds()
*/
public Integer getAccessTokenValiditySeconds() {
return client.getAccessTokenValiditySeconds();
}
/**
* @param accessTokenValiditySeconds
* @see org.mitre.oauth2.model.ClientDetailsEntity#setAccessTokenValiditySeconds(java.lang.Integer)
*/
public void setAccessTokenValiditySeconds(Integer accessTokenValiditySeconds) {
client.setAccessTokenValiditySeconds(accessTokenValiditySeconds);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getRefreshTokenValiditySeconds()
*/
public Integer getRefreshTokenValiditySeconds() {
return client.getRefreshTokenValiditySeconds();
}
/**
* @param refreshTokenValiditySeconds
* @see org.mitre.oauth2.model.ClientDetailsEntity#setRefreshTokenValiditySeconds(java.lang.Integer)
*/
public void setRefreshTokenValiditySeconds(Integer refreshTokenValiditySeconds) {
client.setRefreshTokenValiditySeconds(refreshTokenValiditySeconds);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getRedirectUris()
*/
public Set<String> getRedirectUris() {
return client.getRedirectUris();
}
/**
* @param redirectUris
* @see org.mitre.oauth2.model.ClientDetailsEntity#setRedirectUris(java.util.Set)
*/
public void setRedirectUris(Set<String> redirectUris) {
client.setRedirectUris(redirectUris);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getRegisteredRedirectUri()
*/
public Set<String> getRegisteredRedirectUri() {
return client.getRegisteredRedirectUri();
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getResourceIds()
*/
public Set<String> getResourceIds() {
return client.getResourceIds();
}
/**
* @param resourceIds
* @see org.mitre.oauth2.model.ClientDetailsEntity#setResourceIds(java.util.Set)
*/
public void setResourceIds(Set<String> resourceIds) {
client.setResourceIds(resourceIds);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getAdditionalInformation()
*/
public Map<String, Object> getAdditionalInformation() {
return client.getAdditionalInformation();
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getApplicationType()
*/
public AppType getApplicationType() {
return client.getApplicationType();
}
/**
* @param applicationType
* @see org.mitre.oauth2.model.ClientDetailsEntity#setApplicationType(org.mitre.oauth2.model.ClientDetailsEntity.AppType)
*/
public void setApplicationType(AppType applicationType) {
client.setApplicationType(applicationType);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getClientName()
*/
public String getClientName() {
return client.getClientName();
}
/**
* @param clientName
* @see org.mitre.oauth2.model.ClientDetailsEntity#setClientName(java.lang.String)
*/
public void setClientName(String clientName) {
client.setClientName(clientName);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getTokenEndpointAuthMethod()
*/
public AuthMethod getTokenEndpointAuthMethod() {
return client.getTokenEndpointAuthMethod();
}
/**
* @param tokenEndpointAuthMethod
* @see org.mitre.oauth2.model.ClientDetailsEntity#setTokenEndpointAuthMethod(org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod)
*/
public void setTokenEndpointAuthMethod(AuthMethod tokenEndpointAuthMethod) {
client.setTokenEndpointAuthMethod(tokenEndpointAuthMethod);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getSubjectType()
*/
public SubjectType getSubjectType() {
return client.getSubjectType();
}
/**
* @param subjectType
* @see org.mitre.oauth2.model.ClientDetailsEntity#setSubjectType(org.mitre.oauth2.model.ClientDetailsEntity.SubjectType)
*/
public void setSubjectType(SubjectType subjectType) {
client.setSubjectType(subjectType);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getContacts()
*/
public Set<String> getContacts() {
return client.getContacts();
}
/**
* @param contacts
* @see org.mitre.oauth2.model.ClientDetailsEntity#setContacts(java.util.Set)
*/
public void setContacts(Set<String> contacts) {
client.setContacts(contacts);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getLogoUri()
*/
public String getLogoUri() {
return client.getLogoUri();
}
/**
* @param logoUri
* @see org.mitre.oauth2.model.ClientDetailsEntity#setLogoUri(java.lang.String)
*/
public void setLogoUri(String logoUri) {
client.setLogoUri(logoUri);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getPolicyUri()
*/
public String getPolicyUri() {
return client.getPolicyUri();
}
/**
* @param policyUri
* @see org.mitre.oauth2.model.ClientDetailsEntity#setPolicyUri(java.lang.String)
*/
public void setPolicyUri(String policyUri) {
client.setPolicyUri(policyUri);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getClientUri()
*/
public String getClientUri() {
return client.getClientUri();
}
/**
* @param clientUri
* @see org.mitre.oauth2.model.ClientDetailsEntity#setClientUri(java.lang.String)
*/
public void setClientUri(String clientUri) {
client.setClientUri(clientUri);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getTosUri()
*/
public String getTosUri() {
return client.getTosUri();
}
/**
* @param tosUri
* @see org.mitre.oauth2.model.ClientDetailsEntity#setTosUri(java.lang.String)
*/
public void setTosUri(String tosUri) {
client.setTosUri(tosUri);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getJwksUri()
*/
public String getJwksUri() {
return client.getJwksUri();
}
/**
* @param jwksUri
* @see org.mitre.oauth2.model.ClientDetailsEntity#setJwksUri(java.lang.String)
*/
public void setJwksUri(String jwksUri) {
client.setJwksUri(jwksUri);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getSectorIdentifierUri()
*/
public String getSectorIdentifierUri() {
return client.getSectorIdentifierUri();
}
/**
* @param sectorIdentifierUri
* @see org.mitre.oauth2.model.ClientDetailsEntity#setSectorIdentifierUri(java.lang.String)
*/
public void setSectorIdentifierUri(String sectorIdentifierUri) {
client.setSectorIdentifierUri(sectorIdentifierUri);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getRequestObjectSigningAlg()
*/
public JWSAlgorithmEmbed getRequestObjectSigningAlg() {
return client.getRequestObjectSigningAlg();
}
/**
* @param requestObjectSigningAlg
* @see org.mitre.oauth2.model.ClientDetailsEntity#setRequestObjectSigningAlg(org.mitre.jose.JWSAlgorithmEmbed)
*/
public void setRequestObjectSigningAlg(JWSAlgorithmEmbed requestObjectSigningAlg) {
client.setRequestObjectSigningAlg(requestObjectSigningAlg);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getUserInfoSignedResponseAlg()
*/
public JWSAlgorithmEmbed getUserInfoSignedResponseAlg() {
return client.getUserInfoSignedResponseAlg();
}
/**
* @param userInfoSignedResponseAlg
* @see org.mitre.oauth2.model.ClientDetailsEntity#setUserInfoSignedResponseAlg(org.mitre.jose.JWSAlgorithmEmbed)
*/
public void setUserInfoSignedResponseAlg(JWSAlgorithmEmbed userInfoSignedResponseAlg) {
client.setUserInfoSignedResponseAlg(userInfoSignedResponseAlg);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getUserInfoEncryptedResponseAlg()
*/
public JWEAlgorithmEmbed getUserInfoEncryptedResponseAlg() {
return client.getUserInfoEncryptedResponseAlg();
}
/**
* @param userInfoEncryptedResponseAlg
* @see org.mitre.oauth2.model.ClientDetailsEntity#setUserInfoEncryptedResponseAlg(org.mitre.jose.JWEAlgorithmEmbed)
*/
public void setUserInfoEncryptedResponseAlg(JWEAlgorithmEmbed userInfoEncryptedResponseAlg) {
client.setUserInfoEncryptedResponseAlg(userInfoEncryptedResponseAlg);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getUserInfoEncryptedResponseEnc()
*/
public JWEEncryptionMethodEmbed getUserInfoEncryptedResponseEnc() {
return client.getUserInfoEncryptedResponseEnc();
}
/**
* @param userInfoEncryptedResponseEnc
* @see org.mitre.oauth2.model.ClientDetailsEntity#setUserInfoEncryptedResponseEnc(org.mitre.jose.JWEEncryptionMethodEmbed)
*/
public void setUserInfoEncryptedResponseEnc(JWEEncryptionMethodEmbed userInfoEncryptedResponseEnc) {
client.setUserInfoEncryptedResponseEnc(userInfoEncryptedResponseEnc);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getIdTokenSignedResponseAlg()
*/
public JWSAlgorithmEmbed getIdTokenSignedResponseAlg() {
return client.getIdTokenSignedResponseAlg();
}
/**
* @param idTokenSignedResponseAlg
* @see org.mitre.oauth2.model.ClientDetailsEntity#setIdTokenSignedResponseAlg(org.mitre.jose.JWSAlgorithmEmbed)
*/
public void setIdTokenSignedResponseAlg(JWSAlgorithmEmbed idTokenSignedResponseAlg) {
client.setIdTokenSignedResponseAlg(idTokenSignedResponseAlg);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getIdTokenEncryptedResponseAlg()
*/
public JWEAlgorithmEmbed getIdTokenEncryptedResponseAlg() {
return client.getIdTokenEncryptedResponseAlg();
}
/**
* @param idTokenEncryptedResponseAlg
* @see org.mitre.oauth2.model.ClientDetailsEntity#setIdTokenEncryptedResponseAlg(org.mitre.jose.JWEAlgorithmEmbed)
*/
public void setIdTokenEncryptedResponseAlg(JWEAlgorithmEmbed idTokenEncryptedResponseAlg) {
client.setIdTokenEncryptedResponseAlg(idTokenEncryptedResponseAlg);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getIdTokenEncryptedResponseEnc()
*/
public JWEEncryptionMethodEmbed getIdTokenEncryptedResponseEnc() {
return client.getIdTokenEncryptedResponseEnc();
}
/**
* @param idTokenEncryptedResponseEnc
* @see org.mitre.oauth2.model.ClientDetailsEntity#setIdTokenEncryptedResponseEnc(org.mitre.jose.JWEEncryptionMethodEmbed)
*/
public void setIdTokenEncryptedResponseEnc(JWEEncryptionMethodEmbed idTokenEncryptedResponseEnc) {
client.setIdTokenEncryptedResponseEnc(idTokenEncryptedResponseEnc);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getDefaultMaxAge()
*/
public Integer getDefaultMaxAge() {
return client.getDefaultMaxAge();
}
/**
* @param defaultMaxAge
* @see org.mitre.oauth2.model.ClientDetailsEntity#setDefaultMaxAge(java.lang.Integer)
*/
public void setDefaultMaxAge(Integer defaultMaxAge) {
client.setDefaultMaxAge(defaultMaxAge);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getRequireAuthTime()
*/
public Boolean getRequireAuthTime() {
return client.getRequireAuthTime();
}
/**
* @param requireAuthTime
* @see org.mitre.oauth2.model.ClientDetailsEntity#setRequireAuthTime(java.lang.Boolean)
*/
public void setRequireAuthTime(Boolean requireAuthTime) {
client.setRequireAuthTime(requireAuthTime);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getResponseTypes()
*/
public Set<String> getResponseTypes() {
return client.getResponseTypes();
}
/**
* @param responseTypes
* @see org.mitre.oauth2.model.ClientDetailsEntity#setResponseTypes(java.util.Set)
*/
public void setResponseTypes(Set<String> responseTypes) {
client.setResponseTypes(responseTypes);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getDefaultACRvalues()
*/
public Set<String> getDefaultACRvalues() {
return client.getDefaultACRvalues();
}
/**
* @param defaultACRvalues
* @see org.mitre.oauth2.model.ClientDetailsEntity#setDefaultACRvalues(java.util.Set)
*/
public void setDefaultACRvalues(Set<String> defaultACRvalues) {
client.setDefaultACRvalues(defaultACRvalues);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getInitiateLoginUri()
*/
public String getInitiateLoginUri() {
return client.getInitiateLoginUri();
}
/**
* @param initiateLoginUri
* @see org.mitre.oauth2.model.ClientDetailsEntity#setInitiateLoginUri(java.lang.String)
*/
public void setInitiateLoginUri(String initiateLoginUri) {
client.setInitiateLoginUri(initiateLoginUri);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getPostLogoutRedirectUri()
*/
public String getPostLogoutRedirectUri() {
return client.getPostLogoutRedirectUri();
}
/**
* @param postLogoutRedirectUri
* @see org.mitre.oauth2.model.ClientDetailsEntity#setPostLogoutRedirectUri(java.lang.String)
*/
public void setPostLogoutRedirectUri(String postLogoutRedirectUri) {
client.setPostLogoutRedirectUri(postLogoutRedirectUri);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getRequestUris()
*/
public Set<String> getRequestUris() {
return client.getRequestUris();
}
/**
* @param requestUris
* @see org.mitre.oauth2.model.ClientDetailsEntity#setRequestUris(java.util.Set)
*/
public void setRequestUris(Set<String> requestUris) {
client.setRequestUris(requestUris);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getCreatedAt()
*/
public Date getCreatedAt() {
return client.getCreatedAt();
}
/**
* @param createdAt
* @see org.mitre.oauth2.model.ClientDetailsEntity#setCreatedAt(java.util.Date)
*/
public void setCreatedAt(Date createdAt) {
client.setCreatedAt(createdAt);
}
/**
* @return the registrationAccessToken
*/
public String getRegistrationAccessToken() {
return registrationAccessToken;
}
/**
* @param registrationAccessToken the registrationAccessToken to set
*/
public void setRegistrationAccessToken(String registrationAccessToken) {
this.registrationAccessToken = registrationAccessToken;
}
/**
* @return the registrationClientUri
*/
public String getRegistrationClientUri() {
return registrationClientUri;
}
/**
* @param registrationClientUri the registrationClientUri to set
*/
public void setRegistrationClientUri(String registrationClientUri) {
this.registrationClientUri = registrationClientUri;
}
/**
* @return the clientSecretExpiresAt
*/
public Date getClientSecretExpiresAt() {
return clientSecretExpiresAt;
}
/**
* @param clientSecretExpiresAt the clientSecretExpiresAt to set
*/
public void setClientSecretExpiresAt(Date expiresAt) {
this.clientSecretExpiresAt = expiresAt;
}
/**
* @return the clientIdIssuedAt
*/
public Date getClientIdIssuedAt() {
return clientIdIssuedAt;
}
/**
* @param clientIdIssuedAt the clientIdIssuedAt to set
*/
public void setClientIdIssuedAt(Date issuedAt) {
this.clientIdIssuedAt = issuedAt;
}
}

View File

@ -1,3 +1,18 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.
******************************************************************************/
/**
*
*/
@ -201,6 +216,9 @@ public class SystemScope {
return true;
}
@Override
public String toString() {
return "SystemScope [value=" + value + ", description=" + description + ", icon=" + icon + ", allowDynReg=" + allowDynReg + ", defaultScope=" + defaultScope + "]";
}
}

View File

@ -1,3 +1,18 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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;
import org.mitre.oauth2.model.AuthenticationHolderEntity;

View File

@ -1,3 +1,18 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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;
import org.mitre.oauth2.model.AuthorizationCodeEntity;

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,6 +16,7 @@
package org.mitre.oauth2.repository;
import java.util.List;
import java.util.Set;
import org.mitre.oauth2.model.ClientDetailsEntity;
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
@ -59,4 +60,8 @@ public interface OAuth2TokenRepository {
*/
public OAuth2AccessTokenEntity getAccessTokenForIdToken(OAuth2AccessTokenEntity idToken);
public Set<OAuth2AccessTokenEntity> getAllAccessTokens();
public Set<OAuth2RefreshTokenEntity> getAllRefreshTokens();
}

View File

@ -1,3 +1,18 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.
******************************************************************************/
/**
*
*/

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,6 +16,7 @@
package org.mitre.oauth2.service;
import java.util.List;
import java.util.Set;
import org.mitre.oauth2.model.ClientDetailsEntity;
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
@ -48,12 +49,17 @@ public interface OAuth2TokenEntityService extends AuthorizationServerTokenServic
@Override
public OAuth2AccessTokenEntity getAccessToken(OAuth2Authentication authentication);
public OAuth2AccessTokenEntity getAccessTokenById(Long id);
/**
* @param incomingToken
* @return
*/
public OAuth2AccessTokenEntity getAccessTokenForIdToken(OAuth2AccessTokenEntity idToken);
public OAuth2AccessTokenEntity getAccessTokenById(Long id);
public OAuth2RefreshTokenEntity getRefreshTokenById(Long id);
public Set<OAuth2AccessTokenEntity> getAllAccessTokensForUser(String name);
public Set<OAuth2RefreshTokenEntity> getAllRefreshTokensForUser(String name);
}

View File

@ -1,3 +1,18 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.
******************************************************************************/
/**
*
*/

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -0,0 +1,328 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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;
import java.util.Date;
import java.util.Set;
import org.mitre.jose.JWEAlgorithmEmbed;
import org.mitre.jose.JWEEncryptionMethodEmbed;
import org.mitre.jose.JWSAlgorithmEmbed;
import org.mitre.oauth2.model.ClientDetailsEntity;
import org.mitre.oauth2.model.ClientDetailsEntity.AppType;
import org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod;
import org.mitre.oauth2.model.ClientDetailsEntity.SubjectType;
import org.mitre.oauth2.model.RegisteredClient;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.Sets;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
/**
* @author jricher
*
*/
public class ClientDetailsEntityJsonProcessor {
private static Gson gson = new Gson();
private static JsonParser parser = new JsonParser();
/**
*
* Create an unbound ClientDetailsEntity from the given JSON string.
*
* @param jsonString
* @return the entity if successful, null otherwise
*/
public static ClientDetailsEntity parse(String jsonString) {
JsonElement jsonEl = parser.parse(jsonString);
if (jsonEl.isJsonObject()) {
JsonObject o = jsonEl.getAsJsonObject();
ClientDetailsEntity c = new ClientDetailsEntity();
// TODO: make these field names into constants
// these two fields should only be sent in the update request, and MUST match existing values
c.setClientId(getAsString(o, "client_id"));
c.setClientSecret(getAsString(o, "client_secret"));
// OAuth DynReg
c.setRedirectUris(getAsStringSet(o, "redirect_uris"));
c.setClientName(getAsString(o, "client_name"));
c.setClientUri(getAsString(o, "client_uri"));
c.setLogoUri(getAsString(o, "logo_uri"));
c.setContacts(getAsStringSet(o, "contacts"));
c.setTosUri(getAsString(o, "tos_uri"));
String authMethod = getAsString(o, "token_endpoint_auth_method");
if (authMethod != null) {
c.setTokenEndpointAuthMethod(AuthMethod.getByValue(authMethod));
}
// scope is a space-separated string
String scope = getAsString(o, "scope");
if (scope != null) {
c.setScope(Sets.newHashSet(Splitter.on(" ").split(scope)));
}
c.setGrantTypes(getAsStringSet(o, "grant_types"));
c.setResponseTypes(getAsStringSet(o, "response_types"));
c.setPolicyUri(getAsString(o, "policy_uri"));
c.setJwksUri(getAsString(o, "jwks_uri"));
// OIDC Additions
String appType = getAsString(o, "application_type");
if (appType != null) {
c.setApplicationType(AppType.getByValue(appType));
}
c.setSectorIdentifierUri(getAsString(o, "sector_identifier_uri"));
String subjectType = getAsString(o, "subject_type");
if (subjectType != null) {
c.setSubjectType(SubjectType.getByValue(subjectType));
}
c.setRequestObjectSigningAlg(getAsJwsAlgorithm(o, "request_object_signing_alg"));
c.setUserInfoSignedResponseAlg(getAsJwsAlgorithm(o, "userinfo_signed_response_alg"));
c.setUserInfoEncryptedResponseAlg(getAsJweAlgorithm(o, "userinfo_encrypted_response_alg"));
c.setUserInfoEncryptedResponseEnc(getAsJweEncryptionMethod(o, "userinfo_encrypted_response_enc"));
c.setIdTokenSignedResponseAlg(getAsJwsAlgorithm(o, "id_token_signed_response_alg"));
c.setIdTokenEncryptedResponseAlg(getAsJweAlgorithm(o, "id_token_encrypted_response_alg"));
c.setIdTokenEncryptedResponseEnc(getAsJweEncryptionMethod(o, "id_token_encrypted_response_enc"));
if (o.has("default_max_age")) {
if (o.get("default_max_age").isJsonPrimitive()) {
c.setDefaultMaxAge(o.get("default_max_age").getAsInt());
}
}
if (o.has("require_auth_time")) {
if (o.get("require_auth_time").isJsonPrimitive()) {
c.setRequireAuthTime(o.get("require_auth_time").getAsBoolean());
}
}
c.setDefaultACRvalues(getAsStringSet(o, "default_acr_values"));
c.setInitiateLoginUri(getAsString(o, "initiate_login_uri"));
c.setPostLogoutRedirectUri(getAsString(o, "post_logout_redirect_uri"));
c.setRequestUris(getAsStringSet(o, "request_uris"));
return c;
} else {
return null;
}
}
/**
* Parse the JSON as a RegisteredClient (useful in the dynamic client filter)
*/
public static RegisteredClient parseRegistered(String jsonString) {
JsonElement jsonEl = parser.parse(jsonString);
if (jsonEl.isJsonObject()) {
JsonObject o = jsonEl.getAsJsonObject();
ClientDetailsEntity c = parse(jsonString);
RegisteredClient rc = new RegisteredClient(c);
// get any fields from the registration
rc.setRegistrationAccessToken(getAsString(o, "registration_access_token"));
rc.setRegistrationClientUri(getAsString(o, "registration_client_uri"));
rc.setClientIdIssuedAt(getAsDate(o, "client_id_issued_at"));
rc.setClientSecretExpiresAt(getAsDate(o, "client_secret_expires_at"));
return rc;
} else {
return null;
}
}
/**
* @param c
* @param token
* @param registrationUri
* @return
*/
public static JsonObject serialize(RegisteredClient c) {
JsonObject o = new JsonObject();
o.addProperty("client_id", c.getClientId());
if (c.getClientSecret() != null) {
o.addProperty("client_secret", c.getClientSecret());
if (c.getClientSecretExpiresAt() == null) {
o.addProperty("client_secret_expires_at", 0); // TODO: do we want to let secrets expire?
} else {
o.addProperty("client_secret_expires_at", c.getClientSecretExpiresAt().getTime() / 1000L);
}
}
if (c.getClientIdIssuedAt() != null) {
o.addProperty("client_id_issued_at", c.getClientIdIssuedAt().getTime() / 1000L);
} else if (c.getCreatedAt() != null) {
o.addProperty("client_id_issued_at", c.getCreatedAt().getTime() / 1000L);
}
if (c.getRegistrationAccessToken() != null) {
o.addProperty("registration_access_token", c.getRegistrationAccessToken());
}
if (c.getRegistrationClientUri() != null) {
o.addProperty("registration_client_uri", c.getRegistrationClientUri());
}
// add in all other client properties
// OAuth DynReg
o.add("redirect_uris", getAsArray(c.getRedirectUris()));
o.addProperty("client_name", c.getClientName());
o.addProperty("client_uri", c.getClientUri());
o.addProperty("logo_uri", c.getLogoUri());
o.add("contacts", getAsArray(c.getContacts()));
o.addProperty("tos_uri", c.getTosUri());
o.addProperty("token_endpoint_auth_method", c.getTokenEndpointAuthMethod() != null ? c.getTokenEndpointAuthMethod().getValue() : null);
o.addProperty("scope", c.getScope() != null ? Joiner.on(" ").join(c.getScope()) : null);
o.add("grant_types", getAsArray(c.getGrantTypes()));
o.add("response_types", getAsArray(c.getResponseTypes()));
o.addProperty("policy_uri", c.getPolicyUri());
o.addProperty("jwks_uri", c.getJwksUri());
// OIDC Registration
o.addProperty("application_type", c.getApplicationType() != null ? c.getApplicationType().getValue() : null);
o.addProperty("sector_identifier_uri", c.getSectorIdentifierUri());
o.addProperty("subject_type", c.getSubjectType() != null ? c.getSubjectType().getValue() : null);
o.addProperty("request_object_signing_alg", c.getRequestObjectSigningAlg() != null ? c.getRequestObjectSigningAlg().getAlgorithmName() : null);
o.addProperty("userinfo_signed_response_alg", c.getUserInfoSignedResponseAlg() != null ? c.getUserInfoSignedResponseAlg().getAlgorithmName() : null);
o.addProperty("userinfo_encrypted_response_alg", c.getUserInfoEncryptedResponseAlg() != null ? c.getUserInfoEncryptedResponseAlg().getAlgorithmName() : null);
o.addProperty("userinfo_encrypted_response_enc", c.getUserInfoEncryptedResponseEnc() != null ? c.getUserInfoEncryptedResponseEnc().getAlgorithmName() : null);
o.addProperty("id_token_signed_response_alg", c.getIdTokenSignedResponseAlg() != null ? c.getIdTokenSignedResponseAlg().getAlgorithmName() : null);
o.addProperty("id_token_encrypted_response_alg", c.getIdTokenEncryptedResponseAlg() != null ? c.getIdTokenEncryptedResponseAlg().getAlgorithmName() : null);
o.addProperty("id_token_encrypted_response_enc", c.getIdTokenEncryptedResponseEnc() != null ? c.getIdTokenEncryptedResponseEnc().getAlgorithmName() : null);
o.addProperty("default_max_age", c.getDefaultMaxAge());
o.addProperty("require_auth_time", c.getRequireAuthTime());
o.add("default_acr_values", getAsArray(c.getDefaultACRvalues()));
o.addProperty("initiate_login_uri", c.getInitiateLoginUri());
o.addProperty("post_logout_redirect_uri", c.getPostLogoutRedirectUri());
o.add("request_uris", getAsArray(c.getRequestUris()));
return o;
}
/**
* Gets the value of the given member as a JWE Algorithm, null if it doesn't exist
*/
private static JWEAlgorithmEmbed getAsJweAlgorithm(JsonObject o, String member) {
String s = getAsString(o, member);
if (s != null) {
return JWEAlgorithmEmbed.getForAlgorithmName(s);
} else {
return null;
}
}
/**
* Gets the value of the given member as a JWE Encryption Method, null if it doesn't exist
*/
private static JWEEncryptionMethodEmbed getAsJweEncryptionMethod(JsonObject o, String member) {
String s = getAsString(o, member);
if (s != null) {
return JWEEncryptionMethodEmbed.getForAlgorithmName(s);
} else {
return null;
}
}
/**
* Gets the value of the given member as a JWS Algorithm, null if it doesn't exist
*/
private static JWSAlgorithmEmbed getAsJwsAlgorithm(JsonObject o, String member) {
String s = getAsString(o, member);
if (s != null) {
return JWSAlgorithmEmbed.getForAlgorithmName(s);
} else {
return null;
}
}
/**
* Gets the value of the given member as a string, null if it doesn't exist
*/
private static String getAsString(JsonObject o, String member) {
if (o.has(member)) {
JsonElement e = o.get(member);
if (e != null && e.isJsonPrimitive()) {
return e.getAsString();
} else {
return null;
}
} else {
return null;
}
}
/**
* Gets the value of the given member (expressed as integer seconds since epoch) as a Date
*/
private static Date getAsDate(JsonObject o, String member) {
if (o.has(member)) {
JsonElement e = o.get(member);
if (e != null && e.isJsonPrimitive()) {
return new Date(e.getAsInt() * 1000L);
} else {
return null;
}
} else {
return null;
}
}
/**
* Gets the value of the given given member as a set of strings, null if it doesn't exist
*/
private static Set<String> getAsStringSet(JsonObject o, String member) throws JsonSyntaxException {
if (o.has(member)) {
return gson.fromJson(o.get(member), new TypeToken<Set<String>>(){}.getType());
} else {
return null;
}
}
/**
* Translate a set of strings to a JSON array
* @param value
* @return
*/
private static JsonElement getAsArray(Set<String> value) {
return gson.toJsonTree(value, new TypeToken<Set<String>>(){}.getType());
}
}

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -15,6 +15,12 @@
******************************************************************************/
package org.mitre.openid.connect.config;
import javax.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
/**
@ -27,6 +33,8 @@ package org.mitre.openid.connect.config;
*/
public class ConfigurationPropertiesBean {
private static Logger logger = LoggerFactory.getLogger(ConfigurationPropertiesBean.class);
private String issuer;
private String topbarTitle;
@ -37,6 +45,16 @@ public class ConfigurationPropertiesBean {
}
/**
* Endpoints protected by TLS must have https scheme in the URI.
*/
@PostConstruct
public void checkForHttps() {
if (!StringUtils.startsWithIgnoreCase(issuer, "https")) {
logger.warn("Configured issuer url is not using https scheme.");
}
}
/**
* @return the issuer baseUrl
*/
@ -79,4 +97,4 @@ public class ConfigurationPropertiesBean {
this.logoImageUrl = logoImageUrl;
}
}
}

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -30,12 +30,16 @@ public class ServerConfiguration {
private String tokenEndpointUri;
private String registrationEndpointUri;
private String issuer;
private String jwksUri;
private String userInfoUri;
private String introspectionEndpointUri;
/**
* @return the authorizationEndpointUri
*/
@ -106,4 +110,117 @@ public class ServerConfiguration {
this.userInfoUri = userInfoUri;
}
}
/**
* @return the registrationEndpointUri
*/
public String getRegistrationEndpointUri() {
return registrationEndpointUri;
}
/**
* @param registrationEndpointUri the registrationEndpointUri to set
*/
public void setRegistrationEndpointUri(String registrationEndpointUri) {
this.registrationEndpointUri = registrationEndpointUri;
}
/**
* @return the introspectionEndpointUri
*/
public String getIntrospectionEndpointUri() {
return introspectionEndpointUri;
}
/**
* @param introspectionEndpointUri the introspectionEndpointUri to set
*/
public void setIntrospectionEndpointUri(String introspectionEndpointUri) {
this.introspectionEndpointUri = introspectionEndpointUri;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((authorizationEndpointUri == null) ? 0 : authorizationEndpointUri.hashCode());
result = prime * result + ((introspectionEndpointUri == null) ? 0 : introspectionEndpointUri.hashCode());
result = prime * result + ((issuer == null) ? 0 : issuer.hashCode());
result = prime * result + ((jwksUri == null) ? 0 : jwksUri.hashCode());
result = prime * result + ((registrationEndpointUri == null) ? 0 : registrationEndpointUri.hashCode());
result = prime * result + ((tokenEndpointUri == null) ? 0 : tokenEndpointUri.hashCode());
result = prime * result + ((userInfoUri == null) ? 0 : userInfoUri.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 (!(obj instanceof ServerConfiguration)) {
return false;
}
ServerConfiguration other = (ServerConfiguration) obj;
if (authorizationEndpointUri == null) {
if (other.authorizationEndpointUri != null) {
return false;
}
} else if (!authorizationEndpointUri.equals(other.authorizationEndpointUri)) {
return false;
}
if (introspectionEndpointUri == null) {
if (other.introspectionEndpointUri != null) {
return false;
}
} else if (!introspectionEndpointUri.equals(other.introspectionEndpointUri)) {
return false;
}
if (issuer == null) {
if (other.issuer != null) {
return false;
}
} else if (!issuer.equals(other.issuer)) {
return false;
}
if (jwksUri == null) {
if (other.jwksUri != null) {
return false;
}
} else if (!jwksUri.equals(other.jwksUri)) {
return false;
}
if (registrationEndpointUri == null) {
if (other.registrationEndpointUri != null) {
return false;
}
} else if (!registrationEndpointUri.equals(other.registrationEndpointUri)) {
return false;
}
if (tokenEndpointUri == null) {
if (other.tokenEndpointUri != null) {
return false;
}
} else if (!tokenEndpointUri.equals(other.tokenEndpointUri)) {
return false;
}
if (userInfoUri == null) {
if (other.userInfoUri != null) {
return false;
}
} else if (!userInfoUri.equals(other.userInfoUri)) {
return false;
}
return true;
}
}

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -47,6 +47,7 @@ public class Address {
* @return the formatted address string
*/
@Basic
@Column(name = "formatted")
public String getFormatted() {
return formatted;
}
@ -74,6 +75,7 @@ public class Address {
* @return the locality
*/
@Basic
@Column(name = "locality")
public String getLocality() {
return locality;
}
@ -87,6 +89,7 @@ public class Address {
* @return the region
*/
@Basic
@Column(name = "region")
public String getRegion() {
return region;
}
@ -114,6 +117,7 @@ public class Address {
* @return the country
*/
@Basic
@Column(name = "country")
public String getCountry() {
return country;
}
@ -129,6 +133,7 @@ public class Address {
*/
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "id")
public Long getId() {
return id;
}

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -47,6 +47,7 @@ import com.google.common.collect.Sets;
@NamedQuery(name = "ApprovedSite.getAll", query = "select a from ApprovedSite a"),
@NamedQuery(name = "ApprovedSite.getByUserId", query = "select a from ApprovedSite a where a.userId = :userId"),
@NamedQuery(name = "ApprovedSite.getByClientId", query = "select a from ApprovedSite a where a.clientId = :clientId"),
@NamedQuery(name = "ApprovedSite.getExpired", query = "select a from ApprovedSite a where a.timeoutDate is not null and a.timeoutDate < current_timestamp"),
@NamedQuery(name = "ApprovedSite.getByClientIdAndUserId", query = "select a from ApprovedSite a where a.clientId = :clientId and a.userId = :userId")
})
public class ApprovedSite {
@ -91,6 +92,7 @@ public class ApprovedSite {
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
public Long getId() {
return id;
}
@ -255,5 +257,4 @@ public class ApprovedSite {
public void setApprovedAccessTokens(Set<OAuth2AccessTokenEntity> approvedAccessTokens) {
this.approvedAccessTokens = approvedAccessTokens;
}
}

View File

@ -1,3 +1,18 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.
******************************************************************************/
/**
*
*/
@ -20,7 +35,7 @@ import javax.persistence.Table;
@Entity
@Table(name="blacklisted_site")
@NamedQueries({
@NamedQuery(name = "BlacklistedSite.getAll", query = "select b from BlacklistedSite b"),
@NamedQuery(name = "BlacklistedSite.getAll", query = "select b from BlacklistedSite b")
})
public class BlacklistedSite {
@ -39,6 +54,7 @@ public class BlacklistedSite {
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
public Long getId() {
return id;
}

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -65,6 +65,7 @@ public class DefaultUserInfo implements UserInfo {
*/
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "id")
public Long getId() {
return id;
}
@ -111,6 +112,7 @@ public class DefaultUserInfo implements UserInfo {
*/
@Override
@Basic
@Column(name = "name")
public String getName() {
return name;
}
@ -174,6 +176,7 @@ public class DefaultUserInfo implements UserInfo {
*/
@Override
@Basic
@Column(name = "nickname")
public String getNickname() {
return nickname;
}
@ -189,6 +192,7 @@ public class DefaultUserInfo implements UserInfo {
*/
@Override
@Basic
@Column(name = "profile")
public String getProfile() {
return profile;
}
@ -204,6 +208,7 @@ public class DefaultUserInfo implements UserInfo {
*/
@Override
@Basic
@Column(name = "picture")
public String getPicture() {
return picture;
}
@ -219,6 +224,7 @@ public class DefaultUserInfo implements UserInfo {
*/
@Override
@Basic
@Column(name = "website")
public String getWebsite() {
return website;
}
@ -234,6 +240,7 @@ public class DefaultUserInfo implements UserInfo {
*/
@Override
@Basic
@Column(name = "email")
public String getEmail() {
return email;
}
@ -265,6 +272,7 @@ public class DefaultUserInfo implements UserInfo {
*/
@Override
@Basic
@Column(name = "gender")
public String getGender() {
return gender;
}
@ -296,6 +304,7 @@ public class DefaultUserInfo implements UserInfo {
*/
@Override
@Basic
@Column(name = "locale")
public String getLocale() {
return locale;
}

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,6 +18,7 @@ package org.mitre.openid.connect.model;
import java.util.Date;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
@ -47,6 +48,7 @@ public class Event {
*/
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "id")
public Long getId() {
return id;
}
@ -73,6 +75,7 @@ public class Event {
*/
@Basic
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
@Column(name = "timestamp")
public Date getTimestamp() {
return timestamp;
}

View File

@ -1,3 +1,18 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.util.Date;
@ -39,6 +54,7 @@ public class Nonce {
*/
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "id")
public Long getId() {
return id;
}

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,13 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.mitre.openid.connect.client;
package org.mitre.openid.connect.model;
import java.util.ArrayList;
import java.util.Collection;
import org.mitre.openid.connect.config.ServerConfiguration;
import org.mitre.openid.connect.model.UserInfo;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
@ -34,12 +33,12 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken {
private static final long serialVersionUID = 22100073066377804L;
private final Object principal;
private final ImmutableMap<String, String> 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 final String issuer; // issuer URL (parsed from the id token)
private final String userId; // user id (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 transient UserInfo userInfo; // user info container, don't serialize it b/c it might be huge and can be re-fetched
@ -49,21 +48,21 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken {
*
* Set to authenticated.
*
* Constructs a Principal out of the user_id and issuer.
* @param userId
* Constructs a Principal out of the subject and issuer.
* @param subject
* @param authorities
* @param principal
* @param idToken
*/
public OIDCAuthenticationToken(String userId, String issuer,
public OIDCAuthenticationToken(String subject, String issuer,
UserInfo userInfo, Collection<? extends GrantedAuthority> authorities,
String idTokenValue, String accessTokenValue, String refreshTokenValue) {
super(authorities);
this.principal = ImmutableMap.of("user_id", userId, "issuer", issuer);
this.principal = ImmutableMap.of("sub", subject, "iss", issuer);
this.userInfo = userInfo;
this.userId = userId;
this.sub = subject;
this.issuer = issuer;
this.idTokenValue = idTokenValue;
this.accessTokenValue = accessTokenValue;
@ -79,18 +78,18 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken {
*
* Set to not-authenticated.
*
* Constructs a Principal out of the user_id and issuer.
* @param userId
* Constructs a Principal out of the subject and issuer.
* @param sub
* @param idToken
*/
public OIDCAuthenticationToken(String userId, String issuer,
public OIDCAuthenticationToken(String subject, String issuer,
ServerConfiguration serverConfiguration,
String idTokenValue, String accessTokenValue, String refreshTokenValue) {
super(new ArrayList<GrantedAuthority>(0));
this.principal = ImmutableMap.of("user_id", userId, "issuer", issuer);
this.userId = userId;
this.principal = ImmutableMap.of("sub", subject, "iss", issuer);
this.sub = subject;
this.issuer = issuer;
this.idTokenValue = idTokenValue;
this.accessTokenValue = accessTokenValue;
@ -114,19 +113,16 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken {
return accessTokenValue;
}
/*
* (non-Javadoc)
*
* @see org.springframework.security.core.Authentication#getPrincipal()
/**
* Get the principal of this object, an immutable map of the subject and issuer.
*/
@Override
public Object getPrincipal() {
// TODO Auto-generated method stub
return principal;
}
public String getUserId() {
return userId;
public String getSub() {
return sub;
}
/**
@ -172,4 +168,4 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken {
}
}
}

View File

@ -1,3 +1,18 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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;
@ -195,4 +210,4 @@ public interface UserInfo {
* @param birthdate
*/
public abstract void setBirthdate(String birthdate);
}
}

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -71,6 +71,7 @@ public class WhitelistedSite {
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
public Long getId() {
return id;
}

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -83,4 +83,10 @@ public interface ApprovedSiteRepository {
* @return
*/
public Collection<ApprovedSite> getByClientId(String clientId);
/**
* Get all expired sites
* @return
*/
public Collection<ApprovedSite> getExpired();
}

View File

@ -1,3 +1,18 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.
******************************************************************************/
/**
*
*/

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,3 +1,18 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.repository;
import java.util.Collection;

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -95,4 +95,10 @@ public interface ApprovedSiteService {
* @param client
*/
public void clearApprovedSitesForClient(ClientDetails client);
/**
* Remove all expired approved sites fromt he data store.
* @return
*/
public void clearExpiredSites();
}

View File

@ -1,3 +1,18 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.
******************************************************************************/
/**
*
*/

View File

@ -1,3 +1,18 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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;
import java.util.Collection;

View File

@ -1,3 +1,18 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* 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.
******************************************************************************/
/**
*
*/
@ -21,4 +36,19 @@ public interface StatsService {
*/
public Map<String, Integer> calculateSummaryStats();
/**
* Calculate usage count for all clients
*
* @return a map of id of client object to number of approvals
*/
public Map<Long, Integer> calculateByClientId();
/**
* Calculate the usage count for a single client
*
* @param id the id of the client to search on
* @return
*/
public Integer countForClientId(Long id);
}

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright 2012 The MITRE Corporation
* Copyright 2013 The MITRE Corporation and the MIT Kerberos and Internet Trust Consortuim
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

Some files were not shown because too many files have changed in this diff Show More