From: Mike S. <ms...@us...> - 2007-04-22 15:56:14
|
Update of /cvsroot/wonder/Wonder/Common/Frameworks/EROpenID/Sources/er/openid In directory sc8-pr-cvs9.sourceforge.net:/tmp/cvs-serv27877/Common/Frameworks/EROpenID/Sources/er/openid Added Files: EROFormRedirectionPage.java EROpenIDManager.java IEROResponsePage.java ERODirectAction.java ERORedirectionForm.java IEROFormRedirectionPage.java EROResponse.java EROpenID.java Log Message: Initial import of EROpenID --- NEW FILE: EROFormRedirectionPage.java --- package er.openid; // Generated by the WOLips Templateengine Plug-in at Apr 22, 2007 9:09:53 AM import com.webobjects.appserver.WOComponent; import com.webobjects.appserver.WOContext; /** * EROFormRedirectionPage is a simple implementation of OpenID form redirection. * * @author mschrag */ public class EROFormRedirectionPage extends WOComponent implements IEROFormRedirectionPage { private String _redirectionUrl; public EROFormRedirectionPage(WOContext context) { super(context); } public void setRedirectionUrl(String redirectionUrl) { _redirectionUrl = redirectionUrl; } public String redirectionUrl() { return _redirectionUrl; } } --- NEW FILE: EROpenIDManager.java --- package er.openid; import java.util.Enumeration; import java.util.List; import org.openid4java.association.AssociationException; import org.openid4java.consumer.ConsumerException; import org.openid4java.consumer.ConsumerManager; import org.openid4java.consumer.VerificationResult; import org.openid4java.discovery.DiscoveryException; import org.openid4java.discovery.DiscoveryInformation; import org.openid4java.discovery.Identifier; import org.openid4java.message.AuthRequest; import org.openid4java.message.AuthSuccess; import org.openid4java.message.MessageException; import org.openid4java.message.Parameter; import org.openid4java.message.ParameterList; import org.openid4java.message.ax.AxMessage; import org.openid4java.message.ax.FetchRequest; import org.openid4java.message.ax.FetchResponse; import org.openid4java.util.HttpClientFactory; import org.openid4java.util.ProxyProperties; import com.webobjects.appserver.WOActionResults; import com.webobjects.appserver.WOApplication; import com.webobjects.appserver.WOComponent; import com.webobjects.appserver.WOContext; import com.webobjects.appserver.WORedirect; import com.webobjects.appserver.WORequest; import com.webobjects.appserver.WOSession; import er.extensions.ERXProperties; import er.extensions.ERXRequest; /** * EROpenIDManager is the primary interface to managin an OpenID connection. * * @property er.openid.proxyHostName the host name to use as a proxy (if necessary) * @property er.openid.proxyPort the port to use as a proxy (if necessary) * @property er.openid.formRedirectionPageName the name of the form redirection page to go to * (defaults to EROFormRedirectionPage, should implement IEROFormRedirectionPage) * * @author mschrag */ public class EROpenIDManager { private static final String DISCOVERY_INFO_KEY = "openIDDiscoveryInfo"; private static EROpenIDManager _openIDManager; private ConsumerManager _manager; private EROpenIDManager.Delegate _delegate; /** * EROpenIDManager delegate */ public static interface Delegate { /** * Returns an OpenID fetch request. * * @param userSuppliedString the string the user supplied * @param request the WORequest * @param context the WOContext * @return a FetchRequest */ public FetchRequest createFetchRequest(String userSuppliedString, WORequest request, WOContext context); /** * Called after a response is received from the OpenID server. * * @param verification the original verification result * @param eroResponse the EROResponse wrapper * @param request the WORequest * @param context the WOContext * @return a FetchRequest */ public void responseReceived(VerificationResult verification, EROResponse eroResponse, WORequest request, WOContext context); /** * Returns the URL that the OpenID provider should come back to after authentication. * * @param request the WORequest * @param context the WOContext * @return the URL that the OpenID provider should come back to after authentication */ public String returnToUrl(WORequest request, WOContext context); /** * Gives the delegate an opportunity to rewrite the receiving URL from the return * request after authentication. This may be necessary if you are using rewrite * rules on your webserver, and the returnToUrl does not match the URL that * WebObjects may see in the WORequest. * * @param request the WORequest * @param context the WOContext * @return the rewritten URL */ public String rewriteReceivingUrl(WORequest request, WOContext context); } /** * The default delegate implementation. */ public static class DefaultDelegate implements EROpenIDManager.Delegate { public FetchRequest createFetchRequest(String userSuppliedString, WORequest request, WOContext context) { return null; } public void responseReceived(VerificationResult verification, EROResponse eroResponse, WORequest request, WOContext context) { // DO NOTHING } public String returnToUrl(WORequest request, WOContext context) { String returnToUrl; context._generateCompleteURLs(); try { returnToUrl = context._directActionURL("ERODirectAction/openIDResponse", null, true); } finally { context._generateRelativeURLs(); } return returnToUrl; } public String rewriteReceivingUrl(WORequest request, WOContext context) { StringBuffer receivingUrlBuffer = new StringBuffer(); int serverPort = 0; String serverPortStr = request._serverPort(); if (serverPortStr != null) { serverPort = Integer.parseInt(serverPortStr); } request._completeURLPrefix(receivingUrlBuffer, ERXRequest.isRequestSecure(request), serverPort); receivingUrlBuffer.append(request.uri()); return receivingUrlBuffer.toString(); } } /** * A simple delegate implementation that requests the user's email address. */ public static class EmailDelegate extends EROpenIDManager.DefaultDelegate { public FetchRequest createFetchRequest(String userSuppliedString, WORequest request, WOContext context) { FetchRequest fetchRequest = FetchRequest.createFetchRequest(); fetchRequest.addAttribute("email", "http://schema.openid.net/contact/email", true); return fetchRequest; } } /** * Returns the singleton EROpenIDManager instance. * * @return the singleton EROpenIDManager instance */ public static synchronized EROpenIDManager manager() { if (_openIDManager == null) { try { _openIDManager = new EROpenIDManager(); _openIDManager.setDelegate(new DefaultDelegate()); } catch (ConsumerException e) { throw new RuntimeException("Failed to create EROpenIDManager.", e); } } return _openIDManager; } /** * Constructs a new EROpenIDManager. * * @throws ConsumerException */ protected EROpenIDManager() throws ConsumerException { _manager = new ConsumerManager(); } /** * Set the delegate for this manager if you want to specify a custom * FetchRequest. By default the fetch request asks for the user's email * address. * * @param delegate the new delegate */ public void setDelegate(EROpenIDManager.Delegate delegate) { _delegate = delegate; } /** * Returns whether or not the given string looks like an OpenID auth string. * * @param userSuppliedString the string from the user * @return whether or not the given string looks like an OpenID auth string */ public boolean isOpenIDAuth(String userSuppliedString) { return userSuppliedString != null && userSuppliedString.toLowerCase().startsWith("http://"); } /** * Initiates the authentication request. * * @param userSuppliedString the string supplied by the user * @param request the WORequest * @param context the WOContext * @return the redirection action results * @throws MessageException * @throws DiscoveryException * @throws ConsumerException */ public WOActionResults authRequest(String userSuppliedString, WORequest request, WOContext context) throws MessageException, DiscoveryException, ConsumerException { WOSession session = context.session(); String proxyHostName = ERXProperties.stringForKey("er.openid.proxyHostName"); if (proxyHostName != null) { int proxyPort = ERXProperties.intForKey("er.openid.proxyPort"); // --- Forward proxy setup (only if needed) --- ProxyProperties proxyProps = new ProxyProperties(); proxyProps.setProxyHostName(proxyHostName); proxyProps.setProxyPort(proxyPort); HttpClientFactory.setProxyProperties(proxyProps); } // perform discovery on the user-supplied identifier List discoveries = _manager.discover(userSuppliedString); // attempt to associate with the OpenID provider // and retrieve one service endpoint for authentication DiscoveryInformation discovered = _manager.associate(discoveries); // store the discovery information in the user's session session.setObjectForKey(discovered, EROpenIDManager.DISCOVERY_INFO_KEY); // configure the return_to URL where your application will receive // the authentication responses from the OpenID provider String returnToUrl = _delegate.returnToUrl(request, context); // obtain a AuthRequest message to be sent to the OpenID provider AuthRequest authReq = _manager.authenticate(discovered, returnToUrl); // Attribute Exchange example: fetching the 'email' attribute FetchRequest fetchRequest = _delegate.createFetchRequest(userSuppliedString, request, context); if (fetchRequest != null) { // attach the extension to the authentication request authReq.addExtension(fetchRequest); } WOActionResults results; if (!discovered.isVersion2()) { WORedirect redirect = new WORedirect(context); redirect.setUrl(authReq.getDestinationUrl(true)); results = redirect; } else { String formRedirectionPageName = ERXProperties.stringForKeyWithDefault("er.openid.formRedirectionPageName", EROFormRedirectionPage.class.getName()); WOComponent formRedirectionPage = WOApplication.application().pageWithName(formRedirectionPageName, context); formRedirectionPage.takeValueForKey(authReq.getDestinationUrl(false), "redirectionUrl"); results = formRedirectionPage; } return results; } /** * The callback for verifying the OpenID response. * * @param request the WORequest * @param context the WOContext * @return the OpenID response * @throws MessageException * @throws DiscoveryException * @throws AssociationException */ public EROResponse verifyResponse(WORequest request, WOContext context) throws MessageException, DiscoveryException, AssociationException { WOSession session = context.session(); // extract the parameters from the authentication response // (which comes in as a HTTP request from the OpenID provider) ParameterList responseParameters = new ParameterList(); Enumeration formValueKeyEnum = request.formValueKeys().objectEnumerator(); while (formValueKeyEnum.hasMoreElements()) { String formValueKey = (String) formValueKeyEnum.nextElement(); String formValue = request.stringFormValueForKey(formValueKey); responseParameters.set(new Parameter(formValueKey, formValue)); } // retrieve the previously stored discovery information DiscoveryInformation discovered = (DiscoveryInformation) session.objectForKey(EROpenIDManager.DISCOVERY_INFO_KEY); // extract the receiving URL from the HTTP request String receivingUrl = _delegate.rewriteReceivingUrl(request, context); // verify the response; ConsumerManager needs to be the same // (static) instance used to place the authentication request VerificationResult verification = _manager.verify(receivingUrl, responseParameters, discovered); // examine the verification result and extract the verified identifier FetchResponse fetchResponse = null; Identifier identifier = verification.getVerifiedId(); if (identifier != null) { AuthSuccess authSuccess = (AuthSuccess) verification.getAuthResponse(); if (authSuccess.hasExtension(AxMessage.OPENID_NS_AX)) { fetchResponse = (FetchResponse) authSuccess.getExtension(AxMessage.OPENID_NS_AX); } } EROResponse eroResponse = new EROResponse(identifier, fetchResponse); _delegate.responseReceived(verification, eroResponse, request, context); return eroResponse; } } --- NEW FILE: IEROResponsePage.java --- package er.openid; /** * Implemented by the success and failure page if you are using * the default OpenID direct actions. * * @author mschrag */ public interface IEROResponsePage { /** * Sets the OpenID response from the provider. * * @param response the OpenID provider's response */ public void setOpenIDResponse(EROResponse response); } --- NEW FILE: ERODirectAction.java --- package er.openid; import org.openid4java.association.AssociationException; import org.openid4java.consumer.ConsumerException; import org.openid4java.discovery.DiscoveryException; import org.openid4java.message.MessageException; import com.webobjects.appserver.WOActionResults; import com.webobjects.appserver.WOComponent; import com.webobjects.appserver.WORequest; import er.extensions.ERXDirectAction; import er.extensions.ERXProperties; /** * ERODirectAction contains OpenID direct actions. * * @property er.openid.successPageName the name of the openID success page (should implement IEROResponsePage) * @property er.openid.failurePageName the name of the openID failuer page (should implement IEROResponsePage) * * @author mschrag */ public class ERODirectAction extends ERXDirectAction { public ERODirectAction(WORequest request) { super(request); } /** * openIDRequest initiates the Open ID request. The request must * contain an form value named "identity" that contains the user's * OpenID identity url. You can provide your own request URL if * you'd like. This just calls EROpenIDManager.manager().authRequest. * * @return the redirection or form redirection page * @throws MessageException * @throws DiscoveryException * @throws ConsumerException */ public WOActionResults openIDRequestAction() throws MessageException, DiscoveryException, ConsumerException { String identity = request().stringFormValueForKey("identity"); return EROpenIDManager.manager().authRequest(identity, request(), context()); } /** * openIDResponse is the direct action that is redirected back to * from the OpenID provider. See EROpenIDManager's documentation for * information on overriding this. * * @return the results * @throws MessageException * @throws DiscoveryException * @throws AssociationException */ public WOActionResults openIDResponseAction() throws MessageException, DiscoveryException, AssociationException { EROResponse response = EROpenIDManager.manager().verifyResponse(request(), context()); WOActionResults results; if (response.succeeded()) { String successPageName = ERXProperties.stringForKey("er.openid.successPageName"); if (successPageName == null) { throw new IllegalArgumentException("You must set the property 'er.openid.successPageName'."); } WOComponent successPage = pageWithName(successPageName); if (successPage instanceof IEROResponsePage) { ((IEROResponsePage) successPage).setOpenIDResponse(response); } results = successPage; } else { String failurePageName = ERXProperties.stringForKey("er.openid.failurePageName"); if (failurePageName == null) { throw new IllegalArgumentException("You must set the property 'er.openid.failurePageName'."); } WOComponent failurePage = pageWithName(failurePageName); if (failurePage instanceof IEROResponsePage) { ((IEROResponsePage) failurePage).setOpenIDResponse(response); } results = failurePage; } return results; } } --- NEW FILE: ERORedirectionForm.java --- package er.openid; import com.webobjects.appserver.WOComponent; import com.webobjects.appserver.WOContext; import com.webobjects.foundation.NSArray; /** * ERORedirectionForm provides a simple implementaton of an OpenID * redirection form. * * @binding redirectionUrl the url to submit the form to * @binding formName the name of the form * * @author mschrag */ public class ERORedirectionForm extends WOComponent { public String _repetitionFormKey; public ERORedirectionForm(WOContext context) { super(context); } public boolean synchronizesVariablesWithBindings() { return false; } public NSArray formKeys() { return context().request().formValueKeys(); } public String formValue() { return context().request().stringFormValueForKey(_repetitionFormKey); } } --- NEW FILE: IEROFormRedirectionPage.java --- package er.openid; /** * IEROFormRedirectionPage should be implemented by any form redirection page. * * @author mschrag */ public interface IEROFormRedirectionPage { /** * Sets the OpenID redirection URL to submit the form to. * * @param redirectionUrl the OpenID redirection URL */ public void setRedirectionUrl(String redirectionUrl); } --- NEW FILE: EROResponse.java --- package er.openid; import java.util.List; import org.openid4java.discovery.Identifier; import org.openid4java.message.ax.FetchResponse; import com.webobjects.foundation.NSKeyValueCoding; /** * EROResponse encapsulates the response from an OpenID provider. * * @author mschrag */ public class EROResponse implements NSKeyValueCoding.ErrorHandling { private Identifier _identifier; private FetchResponse _fetchResponse; /** * Construct a new EROResponse. * * @param identifier the OpenID identifier (null if auth failed) * @param fetchResponse the FetchResponse (null if auth failed, or if there were no extended attributes) */ public EROResponse(Identifier identifier, FetchResponse fetchResponse) { _identifier = identifier; _fetchResponse = fetchResponse; } /** * Returns whether or not this auth attempt succeeded. * * @return whether or not this auth attempt succeeded */ public boolean succeeded() { return _identifier != null; } /** * Returns the OpenID identifier * * @return the OpenID identifier */ public Identifier identifier() { return _identifier; } /** * Returns the OpenID FetchResponse that contains extended attributes from the request. * * @return the OpenID FetchResponse */ public FetchResponse fetchResponse() { return _fetchResponse; } public void handleTakeValueForUnboundKey(Object obj, String key) { // ignore } public void unableToSetNullForKey(String key) { } public Object handleQueryWithUnboundKey(String key) { Object value = null; if (_fetchResponse != null) { List values = _fetchResponse.getAttributeValues(key); if (values != null && values.size() > 0) { value = values.get(0); } } return value; } } --- NEW FILE: EROpenID.java --- package er.openid; import er.extensions.ERXFrameworkPrincipal; /** * EROpenID Framework Principal * * @author mschrag */ public class EROpenID extends ERXFrameworkPrincipal { public void finishInitialization() { // DO NOTHING } } |