Repository: shiro Updated Branches: refs/heads/openid4j [created] aef52690d
Initial commit for openid4j support This reverts commit 3a23929a8d3d2f13ebe3365ca66f94d51b5bdbe6. Project: http://git-wip-us.apache.org/repos/asf/shiro/repo Commit: http://git-wip-us.apache.org/repos/asf/shiro/commit/aef52690 Tree: http://git-wip-us.apache.org/repos/asf/shiro/tree/aef52690 Diff: http://git-wip-us.apache.org/repos/asf/shiro/diff/aef52690 Branch: refs/heads/openid4j Commit: aef52690df6105cb260207fb622094fdc8c161ca Parents: e8ba5cb Author: Brian Demers <[email protected]> Authored: Tue Nov 8 09:48:39 2016 -0500 Committer: Brian Demers <[email protected]> Committed: Tue Nov 8 09:49:44 2016 -0500 ---------------------------------------------------------------------- pom.xml | 10 ++ support/openid4j/pom.xml | 91 ++++++++++ .../shiro/openid4j/ConstructedRequest.java | 33 ++++ .../shiro/openid4j/DefaultOpenIdService.java | 148 +++++++++++++++++ .../shiro/openid4j/DiscoveryException.java | 29 ++++ .../shiro/openid4j/DiscoveryIdResolver.java | 27 +++ .../shiro/openid4j/MessageExtensionFactory.java | 31 ++++ .../apache/shiro/openid4j/OpenIdException.java | 31 ++++ .../apache/shiro/openid4j/OpenIdService.java | 29 ++++ .../openid4j/SimpleConstructedRequest.java | 44 +++++ .../shiro/openid4j/ax/AttributeDefinition.java | 34 ++++ .../shiro/openid4j/ax/AttributeProperty.java | 118 +++++++++++++ .../shiro/openid4j/ax/FetchRequestFactory.java | 164 +++++++++++++++++++ .../openid4j/ax/SimpleAttributeDefinition.java | 74 +++++++++ .../shiro/openid4j/realm/RelyingPartyRealm.java | 57 +++++++ .../groovy/AttributeTypeScreenScraper.groovy | 100 +++++++++++ .../openid4j/ax/FetchRequestFactoryTest.groovy | 47 ++++++ .../src/test/resources/log4j.properties | 37 +++++ support/pom.xml | 1 + 19 files changed, 1105 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/shiro/blob/aef52690/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index 8fe6095..be27f19 100644 --- a/pom.xml +++ b/pom.xml @@ -86,6 +86,7 @@ <hsqldb.version>1.8.0.7</hsqldb.version> <jdk.version>1.6</jdk.version> <jetty.version>9.3.0.M1</jetty.version> + <openid4j.version>0.9.5</openid4j.version> <!-- Don't change this version without also changing the shiro-quartz and shiro-features modules' OSGi metadata: --> <quartz.version>1.6.1</quartz.version> @@ -736,6 +737,15 @@ </dependency> <dependency> + <groupId>org.openid4java</groupId> + <artifactId>openid4java-consumer</artifactId> + <!--artifactId>openid4java-server</artifactId--> + <!--artifactId>openid4java-infocard</artifactId--> + <!--artifactId>openid4java-xri</artifactId--> + <!--artifactId>openid4java</artifactId--> + <version>${openid4j.version}</version> + </dependency> + <dependency> <!-- Used for Atlassian Crowd Realm - not required for the framework: --> <groupId>com.atlassian.crowd</groupId> <artifactId>crowd-integration-client</artifactId> http://git-wip-us.apache.org/repos/asf/shiro/blob/aef52690/support/openid4j/pom.xml ---------------------------------------------------------------------- diff --git a/support/openid4j/pom.xml b/support/openid4j/pom.xml new file mode 100644 index 0000000..44c7c01 --- /dev/null +++ b/support/openid4j/pom.xml @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you 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/maven-v4_0_0.xsd"> + + <parent> + <groupId>org.apache.shiro</groupId> + <artifactId>shiro-root</artifactId> + <version>2.alpha.0-SNAPSHOT</version> + <relativePath>../../pom.xml</relativePath> + </parent> + + <modelVersion>4.0.0</modelVersion> + <artifactId>shiro-openid4j</artifactId> + <name>Apache Shiro :: Support :: OpenId4J</name> + <packaging>bundle</packaging> + + <dependencies> + <dependency> + <groupId>org.apache.shiro</groupId> + <artifactId>shiro-core</artifactId> + </dependency> + <dependency> + <groupId>org.apache.shiro</groupId> + <artifactId>shiro-web</artifactId> + </dependency> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.openid4java</groupId> + <artifactId>openid4java-consumer</artifactId> + </dependency> + + <!-- Test dependencies --> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>jcl-over-slf4j</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Bundle-SymbolicName>org.apache.shiro.openid4j</Bundle-SymbolicName> + <Export-Package>org.apache.shiro.openid4j*;version=${project.version}</Export-Package> + <Import-Package> + org.apache.shiro*;version="${shiro.osgi.importRange}", + * + </Import-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + +</project> http://git-wip-us.apache.org/repos/asf/shiro/blob/aef52690/support/openid4j/src/main/java/org/apache/shiro/openid4j/ConstructedRequest.java ---------------------------------------------------------------------- diff --git a/support/openid4j/src/main/java/org/apache/shiro/openid4j/ConstructedRequest.java b/support/openid4j/src/main/java/org/apache/shiro/openid4j/ConstructedRequest.java new file mode 100644 index 0000000..4f3b7f8 --- /dev/null +++ b/support/openid4j/src/main/java/org/apache/shiro/openid4j/ConstructedRequest.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.shiro.openid4j; + +import org.openid4java.discovery.DiscoveryInformation; +import org.openid4java.message.AuthRequest; + +/** + * + * @since 1.2 + */ +public interface ConstructedRequest { + + DiscoveryInformation getDiscoveryInfo(); + + AuthRequest getAuthenticationRequest(); +} http://git-wip-us.apache.org/repos/asf/shiro/blob/aef52690/support/openid4j/src/main/java/org/apache/shiro/openid4j/DefaultOpenIdService.java ---------------------------------------------------------------------- diff --git a/support/openid4j/src/main/java/org/apache/shiro/openid4j/DefaultOpenIdService.java b/support/openid4j/src/main/java/org/apache/shiro/openid4j/DefaultOpenIdService.java new file mode 100644 index 0000000..067e3e4 --- /dev/null +++ b/support/openid4j/src/main/java/org/apache/shiro/openid4j/DefaultOpenIdService.java @@ -0,0 +1,148 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.shiro.openid4j; + +import org.apache.shiro.util.CollectionUtils; +import org.apache.shiro.util.StringUtils; +import org.openid4java.OpenIDException; +import org.openid4java.consumer.ConsumerException; +import org.openid4java.consumer.ConsumerManager; +import org.openid4java.discovery.DiscoveryInformation; +import org.openid4java.message.AuthRequest; +import org.openid4java.message.MessageException; +import org.openid4java.message.MessageExtension; + +import java.util.Collection; +import java.util.List; + +/** + * Default implementation of the {@link OpenIdService} interface. + * + * @since 1.2 + */ +public class DefaultOpenIdService implements OpenIdService { + + private ConsumerManager consumerManager; + private DiscoveryIdResolver discoveryIdResolver; + private Collection<MessageExtensionFactory> messageExtensionFactories; + + + public DefaultOpenIdService() { + try { + //The ConsumerManager class is frustrating - at the time of this implementation + //(2011.02.18), this constructor's source code never throws a ConsumerException - probably left in + //place to be backwards compatible with a previous release that did throw that exception. + //Another failing of checked exceptions and not programming to interfaces... + this.consumerManager = new ConsumerManager(); + } catch (ConsumerException e) { + throw new IllegalStateException(e); + } + } + + public ConsumerManager getConsumerManager() { + return consumerManager; + } + + public void setConsumerManager(ConsumerManager consumerManager) { + this.consumerManager = consumerManager; + } + + public DiscoveryIdResolver getDiscoveryIdResolver() { + return discoveryIdResolver; + } + + public void setDiscoveryIdResolver(DiscoveryIdResolver discoveryIdResolver) { + this.discoveryIdResolver = discoveryIdResolver; + } + + public Collection<MessageExtensionFactory> getMessageExtensionFactories() { + return messageExtensionFactories; + } + + public void setMessageExtensionFactories(Collection<MessageExtensionFactory> messageExtensionFactories) { + this.messageExtensionFactories = messageExtensionFactories; + } + + public ConstructedRequest constructRequest(String providerId, String responseUrl) throws OpenIdException { + String discoveryId = getDiscoveryId(providerId); + + DiscoveryInformation discoveryInfo = getDiscoveryInfo(discoveryId, providerId); + + AuthRequest request = createRequest(discoveryInfo, responseUrl); + + addExtensions(request, discoveryInfo, providerId, discoveryId); + + return createConstructedRequest(request, discoveryInfo, providerId, discoveryId); + } + + private void addExtensions(AuthRequest request, DiscoveryInformation info, String serviceId, String discoveryId) { + if (!CollectionUtils.isEmpty(this.messageExtensionFactories)) { + for( MessageExtensionFactory factory : this.messageExtensionFactories ) { + MessageExtension extension = factory.createMessageExtension(request, info, serviceId, discoveryId); + if (extension != null) { + try { + request.addExtension(extension); + } catch (MessageException e) { + String msg = "Unable to add message extension."; + throw new OpenIdException(msg, e); + } + } + } + } + } + + protected String getDiscoveryId(String providerId) { + String discoveryId = providerId; + if (this.discoveryIdResolver != null) { + discoveryId = this.discoveryIdResolver.resolveDiscoveryId(providerId); + if (!StringUtils.hasText(discoveryId)) { + throw new IllegalStateException("DiscoveryIdResolver returned a null, blank or empty string."); + } + } else { + if (!StringUtils.hasText(providerId)) { + throw new IllegalArgumentException("providerId argument cannot be null, empty or blank."); + } + } + return discoveryId; + } + + protected DiscoveryInformation getDiscoveryInfo(String discoveryId, String providerId) throws DiscoveryException { + try { + List discoveries = consumerManager.discover(discoveryId); + return consumerManager.associate(discoveries); + } catch (OpenIDException e) { + String msg = "Unable to discover OpenId Provider based on resolved discoveryId '" + discoveryId + "' " + + "(specified providerId '" + providerId + "')"; + throw new DiscoveryException(msg, e); + } + } + + protected AuthRequest createRequest(DiscoveryInformation info, String responseUrl) throws OpenIdException { + try { + return consumerManager.authenticate(info, responseUrl); + } catch (OpenIDException e) { + throw new OpenIdException("Unable to create AuthRequest.", e); + } + } + + protected ConstructedRequest createConstructedRequest(AuthRequest request, DiscoveryInformation info, + String providerId, String discoveryId) { + return new SimpleConstructedRequest(request, info); + } +} http://git-wip-us.apache.org/repos/asf/shiro/blob/aef52690/support/openid4j/src/main/java/org/apache/shiro/openid4j/DiscoveryException.java ---------------------------------------------------------------------- diff --git a/support/openid4j/src/main/java/org/apache/shiro/openid4j/DiscoveryException.java b/support/openid4j/src/main/java/org/apache/shiro/openid4j/DiscoveryException.java new file mode 100644 index 0000000..c524c79 --- /dev/null +++ b/support/openid4j/src/main/java/org/apache/shiro/openid4j/DiscoveryException.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.shiro.openid4j; + +/** + * @since 1.2 + */ +public class DiscoveryException extends OpenIdException { + + public DiscoveryException(String message, Throwable cause) { + super(message, cause); + } +} http://git-wip-us.apache.org/repos/asf/shiro/blob/aef52690/support/openid4j/src/main/java/org/apache/shiro/openid4j/DiscoveryIdResolver.java ---------------------------------------------------------------------- diff --git a/support/openid4j/src/main/java/org/apache/shiro/openid4j/DiscoveryIdResolver.java b/support/openid4j/src/main/java/org/apache/shiro/openid4j/DiscoveryIdResolver.java new file mode 100644 index 0000000..dc0fa63 --- /dev/null +++ b/support/openid4j/src/main/java/org/apache/shiro/openid4j/DiscoveryIdResolver.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.shiro.openid4j; + +/** + * @since 1.2 + */ +public interface DiscoveryIdResolver { + + String resolveDiscoveryId(String id); +} http://git-wip-us.apache.org/repos/asf/shiro/blob/aef52690/support/openid4j/src/main/java/org/apache/shiro/openid4j/MessageExtensionFactory.java ---------------------------------------------------------------------- diff --git a/support/openid4j/src/main/java/org/apache/shiro/openid4j/MessageExtensionFactory.java b/support/openid4j/src/main/java/org/apache/shiro/openid4j/MessageExtensionFactory.java new file mode 100644 index 0000000..fc82298 --- /dev/null +++ b/support/openid4j/src/main/java/org/apache/shiro/openid4j/MessageExtensionFactory.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.shiro.openid4j; + +import org.openid4java.discovery.DiscoveryInformation; +import org.openid4java.message.AuthRequest; +import org.openid4java.message.MessageExtension; + +/** + * @since 1.2 + */ +public interface MessageExtensionFactory<T extends MessageExtension> { + + T createMessageExtension(AuthRequest request, DiscoveryInformation info, String serviceId, String discoveryId); +} http://git-wip-us.apache.org/repos/asf/shiro/blob/aef52690/support/openid4j/src/main/java/org/apache/shiro/openid4j/OpenIdException.java ---------------------------------------------------------------------- diff --git a/support/openid4j/src/main/java/org/apache/shiro/openid4j/OpenIdException.java b/support/openid4j/src/main/java/org/apache/shiro/openid4j/OpenIdException.java new file mode 100644 index 0000000..8c0d704 --- /dev/null +++ b/support/openid4j/src/main/java/org/apache/shiro/openid4j/OpenIdException.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.shiro.openid4j; + +import org.apache.shiro.authc.AuthenticationException; + +/** + * @since 1.2 + */ +public class OpenIdException extends AuthenticationException { + + public OpenIdException(String message, Throwable cause) { + super(message, cause); + } +} http://git-wip-us.apache.org/repos/asf/shiro/blob/aef52690/support/openid4j/src/main/java/org/apache/shiro/openid4j/OpenIdService.java ---------------------------------------------------------------------- diff --git a/support/openid4j/src/main/java/org/apache/shiro/openid4j/OpenIdService.java b/support/openid4j/src/main/java/org/apache/shiro/openid4j/OpenIdService.java new file mode 100644 index 0000000..6d7b5ac --- /dev/null +++ b/support/openid4j/src/main/java/org/apache/shiro/openid4j/OpenIdService.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.shiro.openid4j; + +/** + * @since 1.2 + */ +public interface OpenIdService { + + ConstructedRequest constructRequest(String providerId, String responseUrl) throws OpenIdException; + + +} http://git-wip-us.apache.org/repos/asf/shiro/blob/aef52690/support/openid4j/src/main/java/org/apache/shiro/openid4j/SimpleConstructedRequest.java ---------------------------------------------------------------------- diff --git a/support/openid4j/src/main/java/org/apache/shiro/openid4j/SimpleConstructedRequest.java b/support/openid4j/src/main/java/org/apache/shiro/openid4j/SimpleConstructedRequest.java new file mode 100644 index 0000000..d2fda21 --- /dev/null +++ b/support/openid4j/src/main/java/org/apache/shiro/openid4j/SimpleConstructedRequest.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.shiro.openid4j; + +import org.openid4java.discovery.DiscoveryInformation; +import org.openid4java.message.AuthRequest; + +/** + * @since 1.2 + */ +public class SimpleConstructedRequest implements ConstructedRequest { + + private final DiscoveryInformation discoveryInfo; + private final AuthRequest authenticationRequest; + + public SimpleConstructedRequest(AuthRequest authRequest, DiscoveryInformation info) { + this.authenticationRequest = authRequest; + this.discoveryInfo = info; + } + + public DiscoveryInformation getDiscoveryInfo() { + return discoveryInfo; + } + + public AuthRequest getAuthenticationRequest() { + return authenticationRequest; + } +} http://git-wip-us.apache.org/repos/asf/shiro/blob/aef52690/support/openid4j/src/main/java/org/apache/shiro/openid4j/ax/AttributeDefinition.java ---------------------------------------------------------------------- diff --git a/support/openid4j/src/main/java/org/apache/shiro/openid4j/ax/AttributeDefinition.java b/support/openid4j/src/main/java/org/apache/shiro/openid4j/ax/AttributeDefinition.java new file mode 100644 index 0000000..787c56e --- /dev/null +++ b/support/openid4j/src/main/java/org/apache/shiro/openid4j/ax/AttributeDefinition.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.shiro.openid4j.ax; + +/** + * @since 1.2 + */ +public interface AttributeDefinition { + + String getName(); + + String getUri(); + + boolean isRequired(); + + int getCount(); + +} http://git-wip-us.apache.org/repos/asf/shiro/blob/aef52690/support/openid4j/src/main/java/org/apache/shiro/openid4j/ax/AttributeProperty.java ---------------------------------------------------------------------- diff --git a/support/openid4j/src/main/java/org/apache/shiro/openid4j/ax/AttributeProperty.java b/support/openid4j/src/main/java/org/apache/shiro/openid4j/ax/AttributeProperty.java new file mode 100644 index 0000000..8f7714b --- /dev/null +++ b/support/openid4j/src/main/java/org/apache/shiro/openid4j/ax/AttributeProperty.java @@ -0,0 +1,118 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.shiro.openid4j.ax; + +import java.util.HashMap; +import java.util.Map; + +/** + * An Enum representing all de-facto standard <a href="http://www.axschema.org/types/"> + * Attribute Exchange Types</a>. + * + * @since 1.2 + */ +public enum AttributeProperty { + + Username("http://axschema.org/namePerson/friendly", "Alias/Username"), + FullName("http://axschema.org/namePerson", "Full name"), + NamePrefix("http://axschema.org/namePerson/prefix", "Name prefix"), + FirstName("http://axschema.org/namePerson/first", "First name"), + LastName("http://axschema.org/namePerson/last", "Last name"), + MiddleName("http://axschema.org/namePerson/middle", "Middle name"), + NameSuffix("http://axschema.org/namePerson/suffix", "Name suffix"), + CompanyName("http://axschema.org/company/name", "Company name"), + JobTitle("http://axschema.org/company/title", "Job title"), + BirthDate("http://axschema.org/birthDate", "Birth date"), + BirthYear("http://axschema.org/birthDate/birthYear", "Birth year"), + BirthMonth("http://axschema.org/birthDate/birthMonth", "Birth month"), + BirthDay("http://axschema.org/birthDate/birthday", "Birth day"), + PhonePreferred("http://axschema.org/contact/phone/default", "Phone (preferred)"), + PhoneHome("http://axschema.org/contact/phone/home", "Phone (home)"), + PhoneWork("http://axschema.org/contact/phone/business", "Phone (work)"), + PhoneMobile("http://axschema.org/contact/phone/cell", "Phone (mobile)"), + PhoneFax("http://axschema.org/contact/phone/fax", "Phone (fax)"), + Address("http://axschema.org/contact/postalAddress/home", "Address"), + Address2("http://axschema.org/contact/postalAddressAdditional/home", "Address 2"), + City("http://axschema.org/contact/city/home", "City"), + State("http://axschema.org/contact/state/home", "State/Province"), + Country("http://axschema.org/contact/country/home", "Country"), + PostalCode("http://axschema.org/contact/postalCode/home", "Postal code"), + BusinessAddress("http://axschema.org/contact/postalAddress/business", "Address"), + BusinessAddress2("http://axschema.org/contact/postalAddressAdditional/business", "Address 2"), + BusinessCity("http://axschema.org/contact/city/business", "City"), + BusinessState("http://axschema.org/contact/state/business", "State/Province"), + BusinessCountry("http://axschema.org/contact/country/business", "Country"), + BusinessPostalCode("http://axschema.org/contact/postalCode/business", "Postal code"), + Email("http://axschema.org/contact/email", "Email"), + AOLIM("http://axschema.org/contact/IM/AIM", "AOL IM"), + ICQIM("http://axschema.org/contact/IM/ICQ", "ICQ IM"), + MSNIM("http://axschema.org/contact/IM/MSN", "MSN IM"), + YahooIM("http://axschema.org/contact/IM/Yahoo", "Yahoo! IM"), + JabberIM("http://axschema.org/contact/IM/Jabber", "Jabber IM"), + SkypeIM("http://axschema.org/contact/IM/Skype", "Skype IM"), + WebPage("http://axschema.org/contact/web/default", "Web page"), + Blog("http://axschema.org/contact/web/blog", "Blog"), + LinkedInURL("http://axschema.org/contact/web/Linkedin", "LinkedIn URL"), + AmazonURL("http://axschema.org/contact/web/Amazon", "Amazon URL"), + FlickrURL("http://axschema.org/contact/web/Flickr", "Flickr URL"), + DeliciousURL("http://axschema.org/contact/web/Delicious", "del.icio.us URL"), + SpokenName("http://axschema.org/media/spokenname", "Spoken name"), + AudioGreeting("http://axschema.org/media/greeting/audio", "Audio greeting"), + VideoGreeting("http://axschema.org/media/greeting/video", "Video greeting"), + Image("http://axschema.org/media/image/default", "Image"), + SquareImage("http://axschema.org/media/image/aspect11", "Square image"), + Aspect43Image("http://axschema.org/media/image/aspect43", "4:3 aspect image"), + Aspect34Image("http://axschema.org/media/image/aspect34", "3:4 aspect image"), + FaviconImage("http://axschema.org/media/image/favicon", "Favicon image"), + Gender("http://axschema.org/person/gender", "Gender"), + Language("http://axschema.org/pref/language", "Language"), + TimeZone("http://axschema.org/pref/timezone", "Time zone"); + + private static final Map<String, AttributeProperty> caseInsensitiveNameMap; + + static { + caseInsensitiveNameMap = new HashMap<String, AttributeProperty>(); + for (AttributeProperty prop : values()) { + caseInsensitiveNameMap.put(prop.name().toLowerCase(), prop); + } + } + + private final String label; + private final String uri; + + private AttributeProperty(String uri, String label) { + this.uri = uri; + this.label = label; + } + + public static AttributeProperty fromName(String caseInsensitiveName) { + if (caseInsensitiveName == null) { + return null; + } + return caseInsensitiveNameMap.get(caseInsensitiveName.toLowerCase()); + } + + public String getLabel() { + return label; + } + + public String getUri() { + return uri; + } +} http://git-wip-us.apache.org/repos/asf/shiro/blob/aef52690/support/openid4j/src/main/java/org/apache/shiro/openid4j/ax/FetchRequestFactory.java ---------------------------------------------------------------------- diff --git a/support/openid4j/src/main/java/org/apache/shiro/openid4j/ax/FetchRequestFactory.java b/support/openid4j/src/main/java/org/apache/shiro/openid4j/ax/FetchRequestFactory.java new file mode 100644 index 0000000..499119a --- /dev/null +++ b/support/openid4j/src/main/java/org/apache/shiro/openid4j/ax/FetchRequestFactory.java @@ -0,0 +1,164 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.shiro.openid4j.ax; + +import org.apache.shiro.config.ConfigurationException; +import org.apache.shiro.openid4j.MessageExtensionFactory; +import org.apache.shiro.openid4j.OpenIdException; +import org.apache.shiro.util.StringUtils; +import org.openid4java.discovery.DiscoveryInformation; +import org.openid4java.message.AuthRequest; +import org.openid4java.message.MessageException; +import org.openid4java.message.ax.FetchRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +/** + * @since 1.2 + */ +public class FetchRequestFactory implements MessageExtensionFactory<FetchRequest> { + + private static final Logger log = LoggerFactory.getLogger(FetchRequestFactory.class); + + private Map<String, String> providerAttributes; + + public FetchRequestFactory() { + this.providerAttributes = new HashMap<String,String>(); + } + + public Map<String, String> getProviderAttributes() { + return providerAttributes; + } + + public void setProviderAttributes(Map<String, String> providerAttributes) { + this.providerAttributes = providerAttributes; + } + + public FetchRequest createMessageExtension(AuthRequest request, DiscoveryInformation info, String serviceId, String discoveryId) { + + String definition = providerAttributes.get(serviceId); + if (definition == null) { + definition = providerAttributes.get(discoveryId); + } + if (definition == null) { + return null; + } + + String[] attributes = StringUtils.split(definition); + if (attributes == null || attributes.length == 0) { + return null; + } + + FetchRequest fetch = FetchRequest.createFetchRequest(); + + //parse the definition by tokenizing it to get the resulting attribute-specific config + // + //e.g. for a value of + // + // "email, firstName[required=true], lastName" + // + // the resulting token array would equal + // + // { "email", "firstName[required=true]", "lastName" } + // + for (String attribute : attributes) { + //strip the name and extract any attribute-specific config between brackets [ ] + String[] nameAndConfig = attribute.split("\\[", 2); + String name = nameAndConfig[0]; + String config = null; + + if (nameAndConfig.length == 2) { + config = nameAndConfig[1]; + //if there was an open bracket, there was a close bracket, so strip it too: + config = config.substring(0, config.length() - 1); + } + + AttributeDefinition ad = toDefinition(name, config); + + try { + fetch.addAttribute(ad.getName(), ad.getUri(), ad.isRequired(), ad.getCount()); + } catch (MessageException e) { + throw new OpenIdException("Unable to correctly add 'fetch' attribute.", e); + } + } + + return fetch; + } + + protected AttributeDefinition toDefinition(String name, String config) { + + AttributeProperty prop = AttributeProperty.fromName(name); + if (prop == null) { + throw new ConfigurationException("Unable to locate a standard OpenId Attribute property for name '" + + name + "'. Please ensure this name matches one of the constants in the " + + AttributeProperty.class.getName() + " enum (name matching is case insensitive)."); + } + + String uri = prop.getUri(); + boolean required = false; + int count = 0; + + + if (config != null) { + String[] configPairs = StringUtils.split(config); + for (String pair : configPairs) { + String nameValue[] = pair.split("\\=", 2); + if (nameValue.length != 2) { + throw new ConfigurationException("OpenId attribute properties with configuration must be " + + "comma-delimited name/value pairs. Each name/value pair must be separated by the " + + "equals sign, e.g. nameProp[name1=value1, name2=value2, ...]. The string that " + + "caused this error was '" + pair + "'."); + } + String pairName = nameValue[0]; + String pairValue = nameValue[1]; + + if ("uri".equalsIgnoreCase(pairName)) { + uri = pairValue; + } else if ("required".equalsIgnoreCase(pairName)) { + required = Boolean.valueOf(pairValue); + } else if ("count".equalsIgnoreCase(pairName)) { + try { + count = Integer.parseInt(pairValue); + } catch (NumberFormatException e) { + String msg = "Unable to correctly parse 'count' value '" + pairValue + "' for OpenId " + + "attribute '" + name + "'"; + throw new ConfigurationException(msg, e); + } + if (count < 0) { + count = 0; + } + } else { + if (log.isWarnEnabled()) { + log.warn("Unrecognized configuration name/value pair for OpenId attribute '{}': {}={}", + new Object[]{name, pairName, pairValue}); + } + + } + } + } + + + return new SimpleAttributeDefinition(prop.name(), uri, required, count); + } + + +} http://git-wip-us.apache.org/repos/asf/shiro/blob/aef52690/support/openid4j/src/main/java/org/apache/shiro/openid4j/ax/SimpleAttributeDefinition.java ---------------------------------------------------------------------- diff --git a/support/openid4j/src/main/java/org/apache/shiro/openid4j/ax/SimpleAttributeDefinition.java b/support/openid4j/src/main/java/org/apache/shiro/openid4j/ax/SimpleAttributeDefinition.java new file mode 100644 index 0000000..bd7de70 --- /dev/null +++ b/support/openid4j/src/main/java/org/apache/shiro/openid4j/ax/SimpleAttributeDefinition.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.shiro.openid4j.ax; + +import org.apache.shiro.openid4j.ax.AttributeDefinition; + +/** + * @since 1.2 + */ +public class SimpleAttributeDefinition implements AttributeDefinition { + + private String name; + private String uri; + private boolean required; + private int count; + + public SimpleAttributeDefinition() { + } + + public SimpleAttributeDefinition(String name, String uri, boolean required, int count) { + this.name = name; + this.uri = uri; + this.required = required; + this.count = count; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getUri() { + return uri; + } + + public void setUri(String uri) { + this.uri = uri; + } + + public boolean isRequired() { + return required; + } + + public void setRequired(boolean required) { + this.required = required; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } +} http://git-wip-us.apache.org/repos/asf/shiro/blob/aef52690/support/openid4j/src/main/java/org/apache/shiro/openid4j/realm/RelyingPartyRealm.java ---------------------------------------------------------------------- diff --git a/support/openid4j/src/main/java/org/apache/shiro/openid4j/realm/RelyingPartyRealm.java b/support/openid4j/src/main/java/org/apache/shiro/openid4j/realm/RelyingPartyRealm.java new file mode 100644 index 0000000..8f65006 --- /dev/null +++ b/support/openid4j/src/main/java/org/apache/shiro/openid4j/realm/RelyingPartyRealm.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.shiro.openid4j.realm; + +import org.apache.shiro.authc.AuthenticationException; +import org.apache.shiro.authc.AuthenticationInfo; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.openid4j.OpenIdService; +import org.apache.shiro.realm.AuthenticatingRealm; + +/** + * A {@code Realm} implementation that performs OpenID authentication by acting as the "Relying Party" + * (client) to an OpenId Provider (server). + * + * @since 1.2 + */ +public class RelyingPartyRealm extends AuthenticatingRealm { + + private OpenIdService openIdService; + + public RelyingPartyRealm() { + + } + + public OpenIdService getOpenIdService() { + return openIdService; + } + + public void setOpenIdService(OpenIdService openIdService) { + this.openIdService = openIdService; + } + + @Override + protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { + + //TODO + + return null; + + } +} http://git-wip-us.apache.org/repos/asf/shiro/blob/aef52690/support/openid4j/src/test/groovy/AttributeTypeScreenScraper.groovy ---------------------------------------------------------------------- diff --git a/support/openid4j/src/test/groovy/AttributeTypeScreenScraper.groovy b/support/openid4j/src/test/groovy/AttributeTypeScreenScraper.groovy new file mode 100644 index 0000000..d11a8bc --- /dev/null +++ b/support/openid4j/src/test/groovy/AttributeTypeScreenScraper.groovy @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +/** + * @since 1.2 + */ +class AttributeTypeScreenScraper extends GroovyTestCase { + + void testNothing() {} + + //used to generate constants in the AttributeProperty class: + void doTestScrape() { + + //file copied from the OpenId website: + def resource = "http://www.axschema.org/types/"; + + def properties = [] + def property = [:] + + boolean parsing = false; + + resource.toURL().eachLine("UTF-8", { String line -> + + line = line.trim() + + if (line.equals("<table id=\"types\">")) { + parsing = true; + } + if (parsing && line.equals("</table>")) { + parsing = false + } + if (parsing) { + if (line.equals("<tr>") && property.size() == 3) { + properties << property + property = [:] + } + if (line.startsWith("<td") && line.endsWith("</a></td>")) { + int index = line.lastIndexOf("http://"); + line = line.substring(index, line.length() - "</a></td>".length()) + property.uri = line + } else if (line.startsWith("<td>") && line.endsWith("</td>") && !line.contains(" ")) { + line = line.substring(4, line.length() - 5) + property.label = line + + String[] words = property.label.split(" "); + String varName = ""; + for( String s : words ) { + s = s.replace("(", "") + s = s.replace(")", "") + s = s.replace(".", "") + int index = s.indexOf("/") + if (index > 0) { + s = s.substring(0, index) + } + varName += s.capitalize() + } + + //special cases: + if (property.uri.endsWith("business")) { + varName = "Business" + varName; + } + if (varName == "Alias") { + varName = "Username" + } + if (varName == "Yahoo!IM") { + varName = "YahooIM" + } + if (varName == "4:3AspectImage") { + varName = "Aspect43Image" + } + if (varName == "3:4AspectImage") { + varName = "Aspect34Image" + } + property.name = varName; + } + } + }); + for (def prop: properties) { + String d = "${prop.name}(\"${prop.uri}\", \"${prop.label}\"), "; + System.out.println(d); + } + } + +} http://git-wip-us.apache.org/repos/asf/shiro/blob/aef52690/support/openid4j/src/test/groovy/org/apache/shiro/openid4j/ax/FetchRequestFactoryTest.groovy ---------------------------------------------------------------------- diff --git a/support/openid4j/src/test/groovy/org/apache/shiro/openid4j/ax/FetchRequestFactoryTest.groovy b/support/openid4j/src/test/groovy/org/apache/shiro/openid4j/ax/FetchRequestFactoryTest.groovy new file mode 100644 index 0000000..7d72fc4 --- /dev/null +++ b/support/openid4j/src/test/groovy/org/apache/shiro/openid4j/ax/FetchRequestFactoryTest.groovy @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.shiro.openid4j.ax + +import org.openid4java.message.ax.FetchRequest + +/** + * Created by IntelliJ IDEA. + * User: lhazlewood + * Date: 2/21/11 + * Time: 10:04 PM + * To change this template use File | Settings | File Templates. + */ +class FetchRequestFactoryTest extends GroovyTestCase { + + void testCreateWithProviderAttributes() { + + FetchRequestFactory factory = new FetchRequestFactory(); + + factory.providerAttributes.google = "email[count=1], firstName[required=true], lastName" + + FetchRequest request = factory.createMessageExtension(null, null, "google", null); + + assertNotNull request + def list = request.getParameters(); + System.out.println(list); + + } + + +} http://git-wip-us.apache.org/repos/asf/shiro/blob/aef52690/support/openid4j/src/test/resources/log4j.properties ---------------------------------------------------------------------- diff --git a/support/openid4j/src/test/resources/log4j.properties b/support/openid4j/src/test/resources/log4j.properties new file mode 100644 index 0000000..0d51520 --- /dev/null +++ b/support/openid4j/src/test/resources/log4j.properties @@ -0,0 +1,37 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# + +log4j.rootLogger=TRACE, stdout + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n + +# Pattern to output: date priority [category] - message +log4j.appender.logfile.layout=org.apache.log4j.PatternLayout +log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n + +# Spring logging level is WARN +log4j.logger.net.sf.ehcache=INFO + +# General Apache libraries is WARN +log4j.logger.org.apache=WARN + +log4j.logger.org.apache.shiro=TRACE +log4j.logger.org.apache.shiro.util.ThreadContext=WARN \ No newline at end of file http://git-wip-us.apache.org/repos/asf/shiro/blob/aef52690/support/pom.xml ---------------------------------------------------------------------- diff --git a/support/pom.xml b/support/pom.xml index 8886f02..fd7f801 100644 --- a/support/pom.xml +++ b/support/pom.xml @@ -38,6 +38,7 @@ <module>quartz</module> <module>spring</module> <module>guice</module> + <module>openid4j</module> <module>features</module> <module>cas</module> <module>spring-boot</module>
