Author: shijh
Date: Tue Jun 30 18:38:16 2015 New Revision: 1688503 URL: http://svn.apache.org/r1688503 Log: Refs OFBIZ-6135. The oauth2 login icons will appear in /ecomseo/checkLogin page if the seed data files are properly configured and imported into database. Added: ofbiz/trunk/specialpurpose/passport/ ofbiz/trunk/specialpurpose/passport/README (with props) ofbiz/trunk/specialpurpose/passport/build.xml (with props) ofbiz/trunk/specialpurpose/passport/config/ ofbiz/trunk/specialpurpose/passport/config/PassportUiLabels.xml (with props) ofbiz/trunk/specialpurpose/passport/config/gitHubAuth.properties (with props) ofbiz/trunk/specialpurpose/passport/config/linkedInAuth.properties (with props) ofbiz/trunk/specialpurpose/passport/data/ ofbiz/trunk/specialpurpose/passport/data/OAuth2CommonSeedData.xml (with props) ofbiz/trunk/specialpurpose/passport/data/OAuth2GitHubSeedData.xml (with props) ofbiz/trunk/specialpurpose/passport/data/OAuth2LinkedInSeedData.xml (with props) ofbiz/trunk/specialpurpose/passport/entitydef/ ofbiz/trunk/specialpurpose/passport/entitydef/entitymodel.xml (with props) ofbiz/trunk/specialpurpose/passport/ofbiz-component.xml (with props) ofbiz/trunk/specialpurpose/passport/src/ ofbiz/trunk/specialpurpose/passport/src/org/ ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/ ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/ ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/ ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/GitHubEvents.java (with props) ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/LinkedInEvents.java (with props) ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/ ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/GitHubAuthenticator.java (with props) ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/GitHubUserGroupMapper.java (with props) ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/LinkedInAuthenticator.java (with props) ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/LinkedInUserGroupMapper.java (with props) ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/util/ ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/util/PassportUtil.java (with props) ofbiz/trunk/specialpurpose/passport/webapp/ ofbiz/trunk/specialpurpose/passport/webapp/passport/ ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/ ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/actions/ ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/actions/login/ ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/actions/login/getThirdPartyLogins.groovy (with props) ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/controller-passport.xml (with props) ofbiz/trunk/specialpurpose/passport/webapp/passport/images/ ofbiz/trunk/specialpurpose/passport/webapp/passport/images/alipay.png (with props) ofbiz/trunk/specialpurpose/passport/webapp/passport/images/github.png (with props) ofbiz/trunk/specialpurpose/passport/webapp/passport/images/linkedin.png (with props) ofbiz/trunk/specialpurpose/passport/webapp/passport/images/paypal.png (with props) ofbiz/trunk/specialpurpose/passport/webapp/passport/images/qq.png (with props) ofbiz/trunk/specialpurpose/passport/webapp/passport/images/renren.png (with props) ofbiz/trunk/specialpurpose/passport/webapp/passport/images/taobao.png (with props) ofbiz/trunk/specialpurpose/passport/webapp/passport/images/weibo.png (with props) ofbiz/trunk/specialpurpose/passport/webapp/passport/images/weixin.png (with props) ofbiz/trunk/specialpurpose/passport/webapp/passport/login/ ofbiz/trunk/specialpurpose/passport/webapp/passport/login/thirdPartyLogins.ftl (with props) ofbiz/trunk/specialpurpose/passport/widget/ ofbiz/trunk/specialpurpose/passport/widget/PassportScreens.xml (with props) Modified: ofbiz/trunk/.classpath ofbiz/trunk/specialpurpose/build.xml ofbiz/trunk/specialpurpose/component-load.xml ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/customer/newcustomer.ftl ofbiz/trunk/specialpurpose/ecommerce/webapp/ecomseo/WEB-INF/controller.xml ofbiz/trunk/specialpurpose/ecommerce/widget/CommonScreens.xml Modified: ofbiz/trunk/.classpath URL: http://svn.apache.org/viewvc/ofbiz/trunk/.classpath?rev=1688503&r1=1688502&r2=1688503&view=diff ============================================================================== --- ofbiz/trunk/.classpath (original) +++ ofbiz/trunk/.classpath Tue Jun 30 18:38:16 2015 @@ -179,6 +179,7 @@ <classpathentry kind="src" path="specialpurpose/projectmgr/src"/> <classpathentry kind="src" path="specialpurpose/scrum/src"/> <classpathentry kind="src" path="specialpurpose/webpos/src"/> + <classpathentry kind="src" path="specialpurpose/passport/src"/> <classpathentry kind="con" path="GROOVY_SUPPORT" exported="true"/> <classpathentry kind="con" path="GROOVY_DSL_SUPPORT" exported="true"/> <classpathentry kind="output" path="bin"/> Modified: ofbiz/trunk/specialpurpose/build.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/build.xml?rev=1688503&r1=1688502&r2=1688503&view=diff ============================================================================== --- ofbiz/trunk/specialpurpose/build.xml (original) +++ ofbiz/trunk/specialpurpose/build.xml Tue Jun 30 18:38:16 2015 @@ -37,6 +37,7 @@ projectmgr/build.xml, scrum/build.xml, bi/build.xml, - webpos/build.xml + webpos/build.xml, + passport/build.xml "/> </project> Modified: ofbiz/trunk/specialpurpose/component-load.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/component-load.xml?rev=1688503&r1=1688502&r2=1688503&view=diff ============================================================================== --- ofbiz/trunk/specialpurpose/component-load.xml (original) +++ ofbiz/trunk/specialpurpose/component-load.xml Tue Jun 30 18:38:16 2015 @@ -40,4 +40,5 @@ under the License. <load-component component-location="bi"/> <load-component component-location="example"/> <load-component component-location="exampleext"/> + <load-component component-location="passport"/> </component-loader> Modified: ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/customer/newcustomer.ftl URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/customer/newcustomer.ftl?rev=1688503&r1=1688502&r2=1688503&view=diff ============================================================================== --- ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/customer/newcustomer.ftl (original) +++ ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/customer/newcustomer.ftl Tue Jun 30 18:38:16 2015 @@ -51,8 +51,8 @@ under the License. } } function hideShowUsaStates() { - var customerStateElement = document.getElementById('newuserform_stateProvinceGeoId'); - var customerCountryElement = document.getElementById('newuserform_countryGeoId'); + var customerStateElement = document.getElementById('newuserform_stateProvinceGeoId'); + var customerCountryElement = document.getElementById('newuserform_countryGeoId'); if (customerCountryElement.value == "USA" || customerCountryElement.value == "UMI") { customerStateElement.style.display = "block"; } else { Modified: ofbiz/trunk/specialpurpose/ecommerce/webapp/ecomseo/WEB-INF/controller.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ecommerce/webapp/ecomseo/WEB-INF/controller.xml?rev=1688503&r1=1688502&r2=1688503&view=diff ============================================================================== --- ofbiz/trunk/specialpurpose/ecommerce/webapp/ecomseo/WEB-INF/controller.xml (original) +++ ofbiz/trunk/specialpurpose/ecommerce/webapp/ecomseo/WEB-INF/controller.xml Tue Jun 30 18:38:16 2015 @@ -21,6 +21,7 @@ under the License. <site-conf xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/site-conf.xsd"> <include location="component://ecommerce/webapp/ecommerce/WEB-INF/controller.xml"/> + <include location="component://passport/webapp/passport/WEB-INF/controller-passport.xml"/> <description>OFBiz: eCommerce SEO Controller Configuration File</description> <handler name="jsp" type="view" class="org.ofbiz.ecommerce.webapp.view.JspViewHandler"/> Modified: ofbiz/trunk/specialpurpose/ecommerce/widget/CommonScreens.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ecommerce/widget/CommonScreens.xml?rev=1688503&r1=1688502&r2=1688503&view=diff ============================================================================== --- ofbiz/trunk/specialpurpose/ecommerce/widget/CommonScreens.xml (original) +++ ofbiz/trunk/specialpurpose/ecommerce/widget/CommonScreens.xml Tue Jun 30 18:38:16 2015 @@ -336,6 +336,7 @@ under the License. <platform-specific> <html><html-template location="component://ecommerce/webapp/ecommerce/login.ftl"/></html> </platform-specific> + <include-screen name="ListThirdPartyLogins" location="component://passport/widget/PassportScreens.xml"/> <platform-specific> <html><html-template location="component://ecommerce/webapp/ecommerce/order/startanoncheckout.ftl"/></html> </platform-specific> Added: ofbiz/trunk/specialpurpose/passport/README URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/README?rev=1688503&view=auto ============================================================================== --- ofbiz/trunk/specialpurpose/passport/README (added) +++ ofbiz/trunk/specialpurpose/passport/README Tue Jun 30 18:38:16 2015 @@ -0,0 +1,4 @@ +OFBiz Passport Component + +To support users to login with a third party OAuth2 authentication such as Github, LinkedIn and etc. + Propchange: ofbiz/trunk/specialpurpose/passport/README ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/specialpurpose/passport/README ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: ofbiz/trunk/specialpurpose/passport/build.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/build.xml?rev=1688503&view=auto ============================================================================== --- ofbiz/trunk/specialpurpose/passport/build.xml (added) +++ ofbiz/trunk/specialpurpose/passport/build.xml Tue Jun 30 18:38:16 2015 @@ -0,0 +1,51 @@ +<?xml version="1.0"?> +<!-- +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 name="OFBiz - Passport Component" default="jar" basedir="."> + <import file="../../common.xml"/> + + <!-- ================================================================== --> + <!-- Initialization of all property settings --> + <!-- ================================================================== --> + + <property name="desc" value="Ecommerce Passport"/> + <property name="name" value="ofbiz-passport"/> + <property name="ofbiz.home.dir" value="../.."/> + + <path id="local.class.path"> + <fileset dir="../../framework/base/lib" includes="*.jar"/> + <fileset dir="../../framework/base/lib/j2eespecs" includes="*.jar"/> + <fileset dir="../../framework/base/build/lib" includes="*.jar"/> + <fileset dir="../../framework/entity/lib" includes="*.jar"/> + <fileset dir="../../framework/entity/build/lib" includes="*.jar"/> + <fileset dir="../../framework/security/build/lib" includes="*.jar"/> + <fileset dir="../../framework/service/lib" includes="*.jar"/> + <fileset dir="../../framework/service/build/lib" includes="*.jar"/> + <fileset dir="../../framework/minilang/build/lib" includes="*.jar"/> + <fileset dir="../../framework/common/build/lib" includes="*.jar"/> + <fileset dir="../../framework/webapp/build/lib" includes="*.jar"/> + <fileset dir="../../applications/party/build/lib" includes="*.jar"/> + <fileset dir="../../applications/product/build/lib" includes="*.jar"/> + <fileset dir="../../applications/marketing/build/lib" includes="*.jar"/> + <fileset dir="../../applications/order/build/lib" includes="*.jar"/> + <fileset dir="../../applications/accounting/build/lib" includes="*.jar"/> + <fileset dir="../../applications/securityext/build/lib" includes="*.jar"/> + </path> +</project> \ No newline at end of file Propchange: ofbiz/trunk/specialpurpose/passport/build.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/specialpurpose/passport/build.xml ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/trunk/specialpurpose/passport/build.xml ------------------------------------------------------------------------------ svn:mime-type = text/xml Added: ofbiz/trunk/specialpurpose/passport/config/PassportUiLabels.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/config/PassportUiLabels.xml?rev=1688503&view=auto ============================================================================== --- ofbiz/trunk/specialpurpose/passport/config/PassportUiLabels.xml (added) +++ ofbiz/trunk/specialpurpose/passport/config/PassportUiLabels.xml Tue Jun 30 18:38:16 2015 @@ -0,0 +1,98 @@ +<?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. +--> + +<resource xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <property key="PassportApplication"> + <value xml:lang="en">Passport Third Party Auth Application</value> + <value xml:lang="zh">ç¬¬ä¸æ¹è®¤è¯åºç¨ç¨åº</value> + </property> + <property key="ThirdPartyLogin"> + <value xml:lang="en">Third Party Login</value> + <value xml:lang="zh">ç¬¬ä¸æ¹ç»å½</value> + </property> + + <!-- LinkedIn labels --> + <property key="LinkedInFailedToMatchState"> + <value xml:lang="en">Failed to match the state parameter in LinkedIn response. Just try to login again.</value> + <value xml:lang="zh">é¢è±ååºä¸çstateåæ°ä¸ä¸è´ãéè¯ç»å½å³å¯ã</value> + </property> + <property key="RedirectToLinkedInOAuth2NullException"> + <value xml:lang="en">Error while redirecting to LinkedIn authorization URL. Please use other login method for now.</value> + <value xml:lang="zh">转å°é¢è±è®¤è¯ç½åæ¶åºéã请å 使ç¨å ¶å®ç»å½æ¹å¼ã</value> + </property> + <property key="RedirectToLinkedInOAuth2Error"> + <value xml:lang="en">Error while redirecting to LinkedIn authorization URL: ${errorMessage}</value> + <value xml:lang="zh">转å°é¢è±è®¤è¯ç½åæ¶åºéï¼${errorMessage}ã</value> + </property> + <property key="FailedToGetLinkedInAuthorizationCode"> + <value xml:lang="en">Failed to get LinkedIn authorization code.<br>Error: ${error}<br>Error description: ${error_description}</value> + <value xml:lang="zh">è·åé¢è±ææç æ¶åºéã<br>é误: ${error}<br>é误æè¿°: ${error_description}</value> + </property> + <property key="GetLinkedInAuthorizationCodeError"> + <value xml:lang="en">Failed to get LinkedIn authorization code.</value> + <value xml:lang="zh">è·åé¢è±ææç æ¶åºéã</value> + </property> + <property key="GetOAuth2LinkedInConfigError"> + <value xml:lang="en">Failed to get LinkedIn configuration. Please check whether OAuth2LinkedIn entity has your productStoreId configured.</value> + <value xml:lang="zh">è·åé¢è±é ç½®æ¶åºéãè¯·æ£æ¥OAuth2LinkedInå®ä½ä¸æ¯å¦é ç½®äºä½ çåºéºæ è¯(productStoreId)ã</value> + </property> + <property key="GetOAuth2LinkedInAccessTokenError"> + <value xml:lang="en">Failed to get LinkedIn access token.</value> + <value xml:lang="zh">è·åé¢è±è®¿é®ä»¤çæ¶åºéã</value> + </property> + <property key="GetOAuth2LinkedInError"> + <value xml:lang="en">Failed to get OAuth2LinkedIn entity: ${errorMessage}</value> + <value xml:lang="zh">è·åOAuth2LinkedInå®ä½æ¶åºéï¼${errorMessage}</value> + </property> + + <!-- GitHub labels --> + <property key="RedirectToGitHubOAuth2NullException"> + <value xml:lang="en">Error while redirecting to GitHub authorization URL. Please use other login method for now.</value> + <value xml:lang="zh">转å°GitHub认è¯ç½åæ¶åºéã请å 使ç¨å ¶å®ç»å½æ¹å¼ã</value> + </property> + <property key="RedirectToGitHubOAuth2Error"> + <value xml:lang="en">Error while redirecting to GitHub authorization URL: ${errorMessage}</value> + <value xml:lang="zh">转å°GitHub认è¯ç½åæ¶åºéï¼${errorMessage}ã</value> + </property> + <property key="GitHubFailedToMatchState"> + <value xml:lang="en">Failed to match the state parameter in GitHub response. Just try to login again.</value> + <value xml:lang="zh">GitHubååºä¸çstateåæ°ä¸ä¸è´ãéè¯ç»å½å³å¯ã</value> + </property> + <property key="FailedToGetLinkedInAuthorizationCode"> + <value xml:lang="en">Failed to get LinkedIn authorization code.<br>Error: ${error}<br>Error description: ${error_description}</value> + <value xml:lang="zh">è·åé¢è±ææç æ¶åºéã<br>é误: ${error}<br>é误æè¿°: ${error_description}</value> + </property> + <property key="GetGitHubAuthorizationCodeError"> + <value xml:lang="en">Failed to get GitHub authorization code.</value> + <value xml:lang="zh">è·åGitHubææç æ¶åºéã</value> + </property> + <property key="GetOAuth2GitHubConfigError"> + <value xml:lang="en">Failed to get GitHub configuration. Please check whether OAuth2GitHub entity has your productStoreId configured.</value> + <value xml:lang="zh">è·åGitHubé ç½®æ¶åºéãè¯·æ£æ¥OAuth2GitHubå®ä½ä¸æ¯å¦é ç½®äºä½ çåºéºæ è¯(productStoreId)ã</value> + </property> + <property key="GetOAuth2GitHubAccessTokenError"> + <value xml:lang="en">Failed to get GitHub access token: ${error}</value> + <value xml:lang="zh">è·åGitHub访é®ä»¤çæ¶åºéï¼${error}</value> + </property> + <property key="GetOAuth2GitHubError"> + <value xml:lang="en">Failed to get OAuth2GitHub entity: ${errorMessage}</value> + <value xml:lang="zh">è·åOAuth2GitHubå®ä½æ¶åºéï¼${errorMessage}</value> + </property> +</resource> Propchange: ofbiz/trunk/specialpurpose/passport/config/PassportUiLabels.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/specialpurpose/passport/config/PassportUiLabels.xml ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/trunk/specialpurpose/passport/config/PassportUiLabels.xml ------------------------------------------------------------------------------ svn:mime-type = text/xml Added: ofbiz/trunk/specialpurpose/passport/config/gitHubAuth.properties URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/config/gitHubAuth.properties?rev=1688503&view=auto ============================================================================== --- ofbiz/trunk/specialpurpose/passport/config/gitHubAuth.properties (added) +++ ofbiz/trunk/specialpurpose/passport/config/gitHubAuth.properties Tue Jun 30 18:38:16 2015 @@ -0,0 +1,24 @@ +############################################################################### +# 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. +############################################################################### + +github.env.prefix=test + +github.authenticator.enabled=true + +# github.group.map.1=github-user=FULLADMIN Propchange: ofbiz/trunk/specialpurpose/passport/config/gitHubAuth.properties ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/specialpurpose/passport/config/gitHubAuth.properties ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/trunk/specialpurpose/passport/config/gitHubAuth.properties ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: ofbiz/trunk/specialpurpose/passport/config/linkedInAuth.properties URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/config/linkedInAuth.properties?rev=1688503&view=auto ============================================================================== --- ofbiz/trunk/specialpurpose/passport/config/linkedInAuth.properties (added) +++ ofbiz/trunk/specialpurpose/passport/config/linkedInAuth.properties Tue Jun 30 18:38:16 2015 @@ -0,0 +1,24 @@ +############################################################################### +# 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. +############################################################################### + +linkedin.env.prefix=test + +linkedin.authenticator.enabled=true + +# linkedin.group.map.1=linkedin-user=FULLADMIN Propchange: ofbiz/trunk/specialpurpose/passport/config/linkedInAuth.properties ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/specialpurpose/passport/config/linkedInAuth.properties ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/trunk/specialpurpose/passport/config/linkedInAuth.properties ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: ofbiz/trunk/specialpurpose/passport/data/OAuth2CommonSeedData.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/data/OAuth2CommonSeedData.xml?rev=1688503&view=auto ============================================================================== --- ofbiz/trunk/specialpurpose/passport/data/OAuth2CommonSeedData.xml (added) +++ ofbiz/trunk/specialpurpose/passport/data/OAuth2CommonSeedData.xml Tue Jun 30 18:38:16 2015 @@ -0,0 +1,28 @@ +<?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. +--> + +<entity-engine-xml> + + <EnumerationType description="Passport Login Method Type" enumTypeId="ppLoginMethType" hasTable="N" parentTypeId=""/> + <EnumerationType description="Passport Login Provider" enumTypeId="ppLoginProvider" hasTable="N" parentTypeId=""/> + + <EnumerationType description="OAuth2 Login Method Type" enumTypeId="OAuth2" hasTable="N" parentTypeId="ppLoginMethType"/> + +</entity-engine-xml> \ No newline at end of file Propchange: ofbiz/trunk/specialpurpose/passport/data/OAuth2CommonSeedData.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/specialpurpose/passport/data/OAuth2CommonSeedData.xml ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/trunk/specialpurpose/passport/data/OAuth2CommonSeedData.xml ------------------------------------------------------------------------------ svn:mime-type = text/xml Added: ofbiz/trunk/specialpurpose/passport/data/OAuth2GitHubSeedData.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/data/OAuth2GitHubSeedData.xml?rev=1688503&view=auto ============================================================================== --- ofbiz/trunk/specialpurpose/passport/data/OAuth2GitHubSeedData.xml (added) +++ ofbiz/trunk/specialpurpose/passport/data/OAuth2GitHubSeedData.xml Tue Jun 30 18:38:16 2015 @@ -0,0 +1,34 @@ +<?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. +--> + +<entity-engine-xml> + + <EnumerationType description="GitHub Login" enumTypeId="GitHub" hasTable="N" parentTypeId="ppLoginProvider"/> + + <ThirdPartyLogin productStoreId="9000" loginMethTypeId="OAuth2" loginProviderId="GitHub" fromDate="2011-01-01 00:00:00.0" thruDate="" sequenceNum=""/> + + <OAuth2GitHub productStoreId="9000" + clientId="" clientSecret="" + returnUrl="" + localRedirectUri="/ecomseo/gitHubRedirect" + iconUrl="/passport/images/github.png" fromDate="2011-01-01 00:00:00.0" thruDate=""/> + <!-- The returnUrl, i.e. https://yourWebSiteOrIp:8443/ecomseo/githubResponse --> + +</entity-engine-xml> \ No newline at end of file Propchange: ofbiz/trunk/specialpurpose/passport/data/OAuth2GitHubSeedData.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/specialpurpose/passport/data/OAuth2GitHubSeedData.xml ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/trunk/specialpurpose/passport/data/OAuth2GitHubSeedData.xml ------------------------------------------------------------------------------ svn:mime-type = text/xml Added: ofbiz/trunk/specialpurpose/passport/data/OAuth2LinkedInSeedData.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/data/OAuth2LinkedInSeedData.xml?rev=1688503&view=auto ============================================================================== --- ofbiz/trunk/specialpurpose/passport/data/OAuth2LinkedInSeedData.xml (added) +++ ofbiz/trunk/specialpurpose/passport/data/OAuth2LinkedInSeedData.xml Tue Jun 30 18:38:16 2015 @@ -0,0 +1,36 @@ +<?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. +--> + +<entity-engine-xml> + + <EnumerationType description="LinkedIn Login" enumTypeId="LinkedIn" hasTable="N" parentTypeId="ppLoginProvider"/> + + <ThirdPartyLogin productStoreId="9000" loginMethTypeId="OAuth2" loginProviderId="LinkedIn" fromDate="2011-01-01 00:00:00.0" thruDate="" sequenceNum=""/> + + <OAuth2LinkedIn productStoreId="9000" + apiKey="" secretKey="" + testReturnUrl="" + liveReturnUrl="" + localRedirectUri="/ecomseo/linkedInRedirect" + iconUrl="/passport/images/linkedin.png" fromDate="2011-01-01 00:00:00.0" thruDate=""/> + <!-- The testReturnUrl, i.e. https://yourTestWebSiteOrIp:8443/ecomseo/linkedInResponse --> + <!-- The liveReturnUrl, i.e. https://yourLiveWebSiteOrIp:8443/ecomseo/linkedInResponse --> + +</entity-engine-xml> \ No newline at end of file Propchange: ofbiz/trunk/specialpurpose/passport/data/OAuth2LinkedInSeedData.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/specialpurpose/passport/data/OAuth2LinkedInSeedData.xml ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/trunk/specialpurpose/passport/data/OAuth2LinkedInSeedData.xml ------------------------------------------------------------------------------ svn:mime-type = text/xml Added: ofbiz/trunk/specialpurpose/passport/entitydef/entitymodel.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/entitydef/entitymodel.xml?rev=1688503&view=auto ============================================================================== --- ofbiz/trunk/specialpurpose/passport/entitydef/entitymodel.xml (added) +++ ofbiz/trunk/specialpurpose/passport/entitydef/entitymodel.xml Tue Jun 30 18:38:16 2015 @@ -0,0 +1,121 @@ +<?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. +--> + +<entitymodel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/entitymodel.xsd"> + <title>Entity of Passport Component</title> + <description>Data Model Enhancements For Passport</description> + <version>1.0</version> + + <entity entity-name="ThirdPartyLogin" + package-name="org.ofbiz.passport" + title="Third party logins for a specific product store" + default-resource-name="PassportEntityLabels"> + <field name="productStoreId" type="id-ne"></field> + <field name="loginMethTypeId" type="id-ne"></field><!-- i.e. OAuth2 --> + <field name="loginProviderId" type="id-ne"></field><!-- i.e. GitHub --> + <field name="fromDate" type="date-time"></field> + <field name="thruDate" type="date-time"></field> + <field name="sequenceNum" type="numeric"></field> + <prim-key field="productStoreId"/> + <prim-key field="loginMethTypeId"/> + <prim-key field="loginProviderId"/> + <prim-key field="fromDate"/> + <relation type="one" fk-name="PROD_STORE_LOGINS" rel-entity-name="ProductStore"> + <key-map field-name="productStoreId"/> + </relation> + <relation type="one" fk-name="LOGIN_METH_TYPE_ID" rel-entity-name="EnumerationType"> + <key-map field-name="loginMethTypeId" rel-field-name="enumTypeId"/> + </relation> + <relation type="one" fk-name="LOGIN_PROVIDER_ID" rel-entity-name="EnumerationType"> + <key-map field-name="loginProviderId" rel-field-name="enumTypeId"/> + </relation> + </entity> + + <!-- GitHub OAuth --> + <entity entity-name="OAuth2GitHub" + package-name="org.ofbiz.passport" + title="GitHub OAuth Login Config" + default-resource-name="PassportEntityLabels"> + <field name="productStoreId" type="id-ne"></field> + <field name="clientId" type="short-varchar"></field> + <field name="clientSecret" type="short-varchar"></field> + <field name="returnUrl" type="value"></field> + <field name="localRedirectUri" type="short-varchar"></field> + <field name="iconUrl" type="url"></field> + <field name="fromDate" type="date-time"></field> + <field name="thruDate" type="date-time"></field> + <prim-key field="productStoreId"/> + <prim-key field="fromDate"/> + <relation type="one" fk-name="STORE_OAUTH_GITHUB" rel-entity-name="ProductStore"> + <key-map field-name="productStoreId"/> + </relation> + </entity> + + <entity entity-name="GitHubUser" + package-name="org.ofbiz.passport" + title="Store GitHub access token for user" + default-resource-name="PassportEntityLabels"> + <field name="gitHubUserId" type="id-vlong-ne"></field> + <field name="productStoreId" type="id-ne"></field> + <field name="envPrefix" type="short-varchar"></field> + <field name="tokenType" type="short-varchar"></field> + <field name="accessToken" type="value"></field> + <prim-key field="gitHubUserId"/> + <relation type="one" fk-name="GITHUB_USER_STORE" rel-entity-name="ProductStore"> + <key-map field-name="productStoreId"/> + </relation> + </entity> + + <!-- LinkedIn OAuth --> + <entity entity-name="OAuth2LinkedIn" + package-name="org.ofbiz.passport" + title="LinkedIn OAuth Login Config" + default-resource-name="PassportEntityLabels"> + <field name="productStoreId" type="id-ne"></field> + <field name="apiKey" type="short-varchar"></field> + <field name="secretKey" type="short-varchar"></field> + <field name="liveReturnUrl" type="value"></field> + <field name="testReturnUrl" type="value"></field> + <field name="localRedirectUri" type="short-varchar"></field> + <field name="iconUrl" type="url"></field> + <field name="fromDate" type="date-time"></field> + <field name="thruDate" type="date-time"></field> + <prim-key field="productStoreId"/> + <prim-key field="fromDate"/> + <relation type="one" fk-name="STORE_OAUTH_LINKEDIN" rel-entity-name="ProductStore"> + <key-map field-name="productStoreId"/> + </relation> + </entity> + + <entity entity-name="LinkedInUser" + package-name="org.ofbiz.passport" + title="Store LinkedIn access token for user" + default-resource-name="PassportEntityLabels"> + <field name="linkedInUserId" type="id-vlong-ne"></field> + <field name="productStoreId" type="id-ne"></field> + <field name="envPrefix" type="short-varchar"></field> + <field name="accessToken" type="value"></field> + <prim-key field="linkedInUserId"/> + <relation type="one" fk-name="LINKEDIN_USER_STORE" rel-entity-name="ProductStore"> + <key-map field-name="productStoreId"/> + </relation> + </entity> + +</entitymodel> \ No newline at end of file Propchange: ofbiz/trunk/specialpurpose/passport/entitydef/entitymodel.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/specialpurpose/passport/entitydef/entitymodel.xml ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/trunk/specialpurpose/passport/entitydef/entitymodel.xml ------------------------------------------------------------------------------ svn:mime-type = text/xml Added: ofbiz/trunk/specialpurpose/passport/ofbiz-component.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/ofbiz-component.xml?rev=1688503&view=auto ============================================================================== --- ofbiz/trunk/specialpurpose/passport/ofbiz-component.xml (added) +++ ofbiz/trunk/specialpurpose/passport/ofbiz-component.xml Tue Jun 30 18:38:16 2015 @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ofbiz-component name="passport" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/ofbiz-component.xsd"> + <!-- define resource loaders; most common is to use the component resource loader --> + <resource-loader name="main" type="component"/> + + <!-- place the config directory on the classpath to access configuration files --> + <classpath type="dir" location="config"/> + + <!-- load single or multiple external libraries --> + <classpath type="jar" location="build/lib/*"/> + <classpath type="jar" location="lib/*"/> + + <!-- entity resources: model(s), eca(s), group, and data definitions --> + <entity-resource type="model" reader-name="main" loader="main" location="entitydef/entitymodel.xml"/> + + <!-- Seed Data --> + <entity-resource type="data" reader-name="seed" loader="main" location="data/OAuth2CommonSeedData.xml"/> + <entity-resource type="data" reader-name="seed" loader="main" location="data/OAuth2LinkedInSeedData.xml"/> + <entity-resource type="data" reader-name="seed" loader="main" location="data/OAuth2GitHubSeedData.xml"/> + + <!-- service resources: model(s), eca(s) and group definitions --> + <!-- + <service-resource type="model" loader="main" location="servicedef/services.xml"/> + --> + + <!-- web applications; will be mounted when using the embedded container --> + <webapp name="passport" + title="OFBiz Passport" + server="default-server" + location="webapp/passport" + mount-point="/passport" + app-bar-display="false" /> +</ofbiz-component> \ No newline at end of file Propchange: ofbiz/trunk/specialpurpose/passport/ofbiz-component.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/specialpurpose/passport/ofbiz-component.xml ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/trunk/specialpurpose/passport/ofbiz-component.xml ------------------------------------------------------------------------------ svn:mime-type = text/xml Added: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/GitHubEvents.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/GitHubEvents.java?rev=1688503&view=auto ============================================================================== --- ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/GitHubEvents.java (added) +++ ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/GitHubEvents.java Tue Jun 30 18:38:16 2015 @@ -0,0 +1,322 @@ +/******************************************************************************* + * 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.ofbiz.passport.event; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.Map; +import java.util.Random; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.cookie.CookiePolicy; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.params.HttpMethodParams; +import org.ofbiz.passport.user.GitHubAuthenticator; +import org.ofbiz.passport.util.PassportUtil; +import org.ofbiz.base.conversion.ConversionException; +import org.ofbiz.base.conversion.JSONConverters.JSONToMap; +import org.ofbiz.base.crypto.HashCrypt; +import org.ofbiz.base.lang.JSON; +import org.ofbiz.base.util.Debug; +import org.ofbiz.base.util.UtilHttp; +import org.ofbiz.base.util.UtilMisc; +import org.ofbiz.base.util.UtilProperties; +import org.ofbiz.base.util.UtilValidate; +import org.ofbiz.common.authentication.api.AuthenticatorException; +import org.ofbiz.common.login.LoginServices; +import org.ofbiz.entity.Delegator; +import org.ofbiz.entity.GenericEntityException; +import org.ofbiz.entity.GenericValue; +import org.ofbiz.entity.util.EntityUtil; +import org.ofbiz.product.store.ProductStoreWorker; +import org.ofbiz.service.LocalDispatcher; + +/** + * GitHubEvents - Events for GitHub login. + * + * Refs: https://developer.github.com/v3/oauth/ + * + */ +public class GitHubEvents { + + public static final String module = GitHubEvents.class.getName(); + + public static final String resource = "PassportUiLabels"; + + public static final String AuthorizeUri = "/login/oauth/authorize"; + + public static final String TokenServiceUri = "/login/oauth/access_token"; + + public static final String UserApiUri = "/user"; + + public static final String DEFAULT_SCOPE = "user,gist"; + + public static final String ApiEndpoint = "https://api.github.com"; + + public static final String TokenEndpoint = "https://github.com"; + + public static final String SESSION_GITHUB_STATE = "_GITHUB_STATE_"; + + public static final String envPrefix = UtilProperties.getPropertyValue(GitHubAuthenticator.props, "github.env.prefix", "test"); + + /** + * Redirect to GitHub login page. + * + * @return + */ + public static String gitHubRedirect(HttpServletRequest request, HttpServletResponse response) { + GenericValue oauth2GitHub = getOAuth2GitHubConfig(request); + if (UtilValidate.isEmpty(oauth2GitHub)) { + return "error"; + } + + String clientId = oauth2GitHub.getString(PassportUtil.COMMON_CLIENT_ID); + String returnURI = oauth2GitHub.getString(PassportUtil.COMMON_RETURN_RUL); + + // Get user authorization code + try { + String state = System.currentTimeMillis() + String.valueOf((new Random(10)).nextLong()); + request.getSession().setAttribute(SESSION_GITHUB_STATE, state); + String redirectUrl = TokenEndpoint + AuthorizeUri + + "?client_id=" + clientId + + "&scope=" + DEFAULT_SCOPE + + "&redirect_uri=" + URLEncoder.encode(returnURI, "UTF-8") + + "&state=" + state; + Debug.logInfo("Request to GitHub: " + redirectUrl, module); + response.sendRedirect(redirectUrl); + } catch (NullPointerException e) { + String errMsg = UtilProperties.getMessage(resource, "RedirectToGitHubOAuth2NullException", UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + return "error"; + } catch (IOException e) { + Map<String, String> messageMap = UtilMisc.toMap("errorMessage", e.toString()); + String errMsg = UtilProperties.getMessage(resource, "RedirectToGitHubOAuth2Error", messageMap, UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + return "error"; + } + + return "success"; + } + + /** + * Parse GitHub login response and login the user if possible. + * + * @return + */ + public static String parseGitHubResponse(HttpServletRequest request, HttpServletResponse response) { + String authorizationCode = request.getParameter(PassportUtil.COMMON_CODE); + String state = request.getParameter(PassportUtil.COMMON_STATE); + if (!state.equals(request.getSession().getAttribute(SESSION_GITHUB_STATE))) { + String errMsg = UtilProperties.getMessage(resource, "GitHubFailedToMatchState", UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + return "error"; + } + if (UtilValidate.isEmpty(authorizationCode)) { + String error = request.getParameter(PassportUtil.COMMON_ERROR); + String errorDescpriton = request.getParameter(PassportUtil.COMMON_ERROR_DESCRIPTION); + String errMsg = null; + try { + errMsg = UtilProperties.getMessage(resource, "FailedToGetGitHubAuthorizationCode", UtilMisc.toMap(PassportUtil.COMMON_ERROR, error, PassportUtil.COMMON_ERROR_DESCRIPTION, URLDecoder.decode(errorDescpriton, "UTF-8")), UtilHttp.getLocale(request)); + } catch (UnsupportedEncodingException e) { + errMsg = UtilProperties.getMessage(resource, "GetGitHubAuthorizationCodeError", UtilHttp.getLocale(request)); + } + request.setAttribute("_ERROR_MESSAGE_", errMsg); + return "error"; + } + Debug.logInfo("GitHub authorization code: " + authorizationCode, module); + + GenericValue oauth2GitHub = getOAuth2GitHubConfig(request); + if (UtilValidate.isEmpty(oauth2GitHub)) { + String errMsg = UtilProperties.getMessage(resource, "GetOAuth2GitHubConfigError", UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + return "error"; + } + String clientId = oauth2GitHub.getString(PassportUtil.COMMON_CLIENT_ID); + String secret = oauth2GitHub.getString(PassportUtil.COMMON_CLIENT_SECRET); + String returnURI = oauth2GitHub.getString(PassportUtil.COMMON_RETURN_RUL); + + // Grant token from authorization code and oauth2 token + // Use the authorization code to obtain an access token + String accessToken = null; + String tokenType = null; + + HttpClient jsonClient = new HttpClient(); + PostMethod postMethod = new PostMethod(TokenEndpoint + TokenServiceUri); + try { + HttpMethodParams params = new HttpMethodParams(); + String queryString = "client_id=" + clientId + + "&client_secret=" + secret + + "&code=" + authorizationCode + + "&redirect_uri=" + URLEncoder.encode(returnURI, "UTF-8"); + // Debug.logInfo("GitHub get access token query string: " + queryString, module); + postMethod.setQueryString(queryString); + params.setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY); + postMethod.setParams(params); + postMethod.setRequestHeader(PassportUtil.ACCEPT_HEADER, "application/json"); + jsonClient.executeMethod(postMethod); + // Debug.logInfo("GitHub get access token response code: " + postMethod.getStatusCode(), module); + // Debug.logInfo("GitHub get access token response content: " + postMethod.getResponseBodyAsString(1024), module); + if (postMethod.getStatusCode() == HttpStatus.SC_OK) { + // Debug.logInfo("Json Response from GitHub: " + postMethod.getResponseBodyAsString(1024), module); + JSON jsonObject = JSON.from(postMethod.getResponseBodyAsString(1024)); + JSONToMap jsonMap = new JSONToMap(); + Map<String, Object> userMap = jsonMap.convert(jsonObject); + accessToken = (String) userMap.get("access_token"); + tokenType = (String) userMap.get("token_type"); + // Debug.logInfo("Generated Access Token : " + accessToken, module); + // Debug.logInfo("Token Type: " + tokenType, module); + } else { + String errMsg = UtilProperties.getMessage(resource, "GetOAuth2GitHubAccessTokenError", UtilMisc.toMap("error", postMethod.getResponseBodyAsString()), UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + return "error"; + } + } catch (UnsupportedEncodingException e) { + request.setAttribute("_ERROR_MESSAGE_", e.toString()); + return "error"; + } catch (HttpException e) { + request.setAttribute("_ERROR_MESSAGE_", e.toString()); + return "error"; + } catch (IOException e) { + request.setAttribute("_ERROR_MESSAGE_", e.toString()); + return "error"; + } catch (ConversionException e) { + request.setAttribute("_ERROR_MESSAGE_", e.toString()); + return "error"; + } finally { + postMethod.releaseConnection(); + } + + // Get User Profile + GetMethod getMethod = new GetMethod(ApiEndpoint + UserApiUri); + Map<String, Object> userInfo = null; + try { + userInfo = GitHubAuthenticator.getUserInfo(getMethod, accessToken, tokenType, UtilHttp.getLocale(request)); + } catch (HttpException e) { + request.setAttribute("_ERROR_MESSAGE_", e.toString()); + return "error"; + } catch (IOException e) { + request.setAttribute("_ERROR_MESSAGE_", e.toString()); + return "error"; + } catch (AuthenticatorException e) { + request.setAttribute("_ERROR_MESSAGE_", e.toString()); + return "error"; + } finally { + getMethod.releaseConnection(); + } + // Debug.logInfo("GitHub User Info:" + userInfo, module); + + // Store the user info and check login the user + return checkLoginGitHubUser(request, userInfo, accessToken); + } + + private static String checkLoginGitHubUser(HttpServletRequest request, Map<String, Object> userInfo, String accessToken) { + Delegator delegator = (Delegator) request.getAttribute("delegator"); + LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher"); + String productStoreId = ProductStoreWorker.getProductStoreId(request); + String gitHubUserId = (String) userInfo.get("login"); + GenericValue gitHubUser = null; + try { + gitHubUser = delegator.findOne("GitHubUser", UtilMisc.toMap("gitHubUserId", gitHubUserId), false); + } catch (GenericEntityException e) { + request.setAttribute("_ERROR_MESSAGE_", e.getMessage()); + return "error"; + } + if (UtilValidate.isNotEmpty(gitHubUser)) { + boolean dataChanged = false; + if (!accessToken.equals(gitHubUser.getString("accessToken"))) { + gitHubUser.set("accessToken", accessToken); + dataChanged = true; + } + if (!envPrefix.equals(gitHubUser.getString("envPrefix"))) { + gitHubUser.set("envPrefix", envPrefix); + dataChanged = true; + } + if (!productStoreId.equals(gitHubUser.getString("productStoreId"))) { + gitHubUser.set("productStoreId", productStoreId); + dataChanged = true; + } + if (dataChanged) { + try { + gitHubUser.store(); + } catch (GenericEntityException e) { + Debug.logError(e.getMessage(), module); + } + } + } else { + gitHubUser = delegator.makeValue("GitHubUser", UtilMisc.toMap("accessToken", accessToken, + "productStoreId", productStoreId, + "envPrefix", envPrefix, + "gitHubUserId", gitHubUserId)); + try { + gitHubUser.create(); + } catch (GenericEntityException e) { + Debug.logError(e.getMessage(), module); + } + } + try { + GenericValue userLogin = EntityUtil.getFirst(delegator.findByAnd("UserLogin", UtilMisc.toMap("externalAuthId", gitHubUserId), null, false)); + GitHubAuthenticator authn = new GitHubAuthenticator(); + authn.initialize(dispatcher); + if (UtilValidate.isEmpty(userLogin)) { + String userLoginId = authn.createUser(userInfo); + userLogin = delegator.findOne("UserLogin", UtilMisc.toMap("userLoginId", userLoginId), false); + } + String password = PassportUtil.randomString(); + boolean useEncryption = "true".equals(UtilProperties.getPropertyValue("security.properties", "password.encrypt")); + userLogin.set("currentPassword", useEncryption ? HashCrypt.digestHash(LoginServices.getHashType(), null, password) : password); + userLogin.store(); + request.setAttribute("USERNAME", userLogin.getString("userLoginId")); + request.setAttribute("PASSWORD", password); + } catch (GenericEntityException e) { + Debug.logError(e.getMessage(), module); + request.setAttribute("_ERROR_MESSAGE_", e.toString()); + return "error"; + } catch (AuthenticatorException e) { + Debug.logError(e.getMessage(), module); + request.setAttribute("_ERROR_MESSAGE_", e.toString()); + return "error"; + } + return "success"; + } + + public static GenericValue getOAuth2GitHubConfig(HttpServletRequest request) { + Delegator delegator = (Delegator) request.getAttribute("delegator"); + String productStoreId = ProductStoreWorker.getProductStoreId(request); + try { + return getOAuth2GitHubConfig(delegator, productStoreId); + } catch (GenericEntityException e) { + Map<String, String> messageMap = UtilMisc.toMap("errorMessage", e.toString()); + String errMsg = UtilProperties.getMessage(resource, "GetOAuth2GitHubError", messageMap, UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + } + return null; + } + + public static GenericValue getOAuth2GitHubConfig(Delegator delegator, String productStoreId) throws GenericEntityException { + return EntityUtil.getFirst(EntityUtil.filterByDate(delegator.findByAnd("OAuth2GitHub", UtilMisc.toMap("productStoreId", productStoreId), null, false))); + } +} Propchange: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/GitHubEvents.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/GitHubEvents.java ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/GitHubEvents.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/LinkedInEvents.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/LinkedInEvents.java?rev=1688503&view=auto ============================================================================== --- ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/LinkedInEvents.java (added) +++ ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/LinkedInEvents.java Tue Jun 30 18:38:16 2015 @@ -0,0 +1,326 @@ +/******************************************************************************* + * 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.ofbiz.passport.event; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.Map; +import java.util.Random; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.cookie.CookiePolicy; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.params.HttpMethodParams; +import org.ofbiz.passport.user.LinkedInAuthenticator; +import org.ofbiz.passport.util.PassportUtil; +import org.ofbiz.base.conversion.ConversionException; +import org.ofbiz.base.conversion.JSONConverters.JSONToMap; +import org.ofbiz.base.crypto.HashCrypt; +import org.ofbiz.base.lang.JSON; +import org.ofbiz.base.util.Debug; +import org.ofbiz.base.util.UtilHttp; +import org.ofbiz.base.util.UtilMisc; +import org.ofbiz.base.util.UtilProperties; +import org.ofbiz.base.util.UtilValidate; +import org.ofbiz.common.authentication.api.AuthenticatorException; +import org.ofbiz.common.login.LoginServices; +import org.ofbiz.entity.Delegator; +import org.ofbiz.entity.GenericEntityException; +import org.ofbiz.entity.GenericValue; +import org.ofbiz.entity.util.EntityUtil; +import org.ofbiz.product.store.ProductStoreWorker; +import org.ofbiz.service.LocalDispatcher; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +/** + * LinkedEvents - Events for LinkedIn login. + * + * Refs: https://developer.linkedin.com/documents/authentication + * + */ +public class LinkedInEvents { + + public static final String module = LinkedInEvents.class.getName(); + + public static final String resource = "PassportUiLabels"; + + public static final String AuthorizeUri = "/uas/oauth2/authorization"; + + public static final String TokenServiceUri = "/uas/oauth2/accessToken"; + + public static final String UserApiUri = "/v1/people/~"; + + public static final String DEFAULT_SCOPE = "r_basicprofile%20r_emailaddress"; + + public static final String TokenEndpoint = "https://www.linkedin.com"; + + public static final String SESSION_LINKEDIN_STATE = "_LINKEDIN_STATE_"; + + public static final String envPrefix = UtilProperties.getPropertyValue(LinkedInAuthenticator.props, "linkedin.env.prefix", "test"); + + /** + * Redirect to LinkedIn login page. + * + * @return + */ + public static String linkedInRedirect(HttpServletRequest request, HttpServletResponse response) { + GenericValue oauth2LinkedIn = getOAuth2LinkedInConfig(request); + if (UtilValidate.isEmpty(oauth2LinkedIn)) { + return "error"; + } + + String clientId = oauth2LinkedIn.getString(PassportUtil.ApiKeyLabel); + String returnURI = oauth2LinkedIn.getString(envPrefix + PassportUtil.ReturnUrlLabel); + + // Get user authorization code + try { + String state = System.currentTimeMillis() + String.valueOf((new Random(10)).nextLong()); + request.getSession().setAttribute(SESSION_LINKEDIN_STATE, state); + String redirectUrl = TokenEndpoint + AuthorizeUri + + "?client_id=" + clientId + + "&response_type=code" + + "&scope=" + DEFAULT_SCOPE + + "&redirect_uri=" + URLEncoder.encode(returnURI, "UTF-8") + + "&state=" + state; + response.sendRedirect(redirectUrl); + } catch (NullPointerException e) { + String errMsg = UtilProperties.getMessage(resource, "RedirectToLinkedInOAuth2NullException", UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + return "error"; + } catch (IOException e) { + Map<String, String> messageMap = UtilMisc.toMap("errorMessage", e.toString()); + String errMsg = UtilProperties.getMessage(resource, "RedirectToLinkedInOAuth2Error", messageMap, UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + return "error"; + } + + return "success"; + } + + /** + * Parse LinkedIn login response and login the user if possible. + * + * @return + */ + public static String parseLinkedInResponse(HttpServletRequest request, HttpServletResponse response) { + String authorizationCode = request.getParameter(PassportUtil.COMMON_CODE); + String state = request.getParameter(PassportUtil.COMMON_STATE); + if (!state.equals(request.getSession().getAttribute(SESSION_LINKEDIN_STATE))) { + String errMsg = UtilProperties.getMessage(resource, "LinkedInFailedToMatchState", UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + return "error"; + } + if (UtilValidate.isEmpty(authorizationCode)) { + String error = request.getParameter(PassportUtil.COMMON_ERROR); + String errorDescpriton = request.getParameter(PassportUtil.COMMON_ERROR_DESCRIPTION); + String errMsg = null; + try { + errMsg = UtilProperties.getMessage(resource, "FailedToGetLinkedInAuthorizationCode", UtilMisc.toMap(PassportUtil.COMMON_ERROR, error, PassportUtil.COMMON_ERROR_DESCRIPTION, URLDecoder.decode(errorDescpriton, "UTF-8")), UtilHttp.getLocale(request)); + } catch (UnsupportedEncodingException e) { + errMsg = UtilProperties.getMessage(resource, "GetLinkedInAuthorizationCodeError", UtilHttp.getLocale(request)); + } + request.setAttribute("_ERROR_MESSAGE_", errMsg); + return "error"; + } + // Debug.logInfo("LinkedIn authorization code: " + authorizationCode, module); + + GenericValue oauth2LinkedIn = getOAuth2LinkedInConfig(request); + if (UtilValidate.isEmpty(oauth2LinkedIn)) { + String errMsg = UtilProperties.getMessage(resource, "GetOAuth2LinkedInConfigError", UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + return "error"; + } + String clientId = oauth2LinkedIn.getString(PassportUtil.ApiKeyLabel); + String secret = oauth2LinkedIn.getString(PassportUtil.SecretKeyLabel); + String returnURI = oauth2LinkedIn.getString(envPrefix + PassportUtil.ReturnUrlLabel); + + // Grant token from authorization code and oauth2 token + // Use the authorization code to obtain an access token + String accessToken = null; + + HttpClient jsonClient = new HttpClient(); + PostMethod postMethod = new PostMethod(TokenEndpoint + TokenServiceUri); + try { + HttpMethodParams params = new HttpMethodParams(); + String queryString = "client_id=" + clientId + + "&client_secret=" + secret + + "&grant_type=authorization_code" + + "&code=" + authorizationCode + + "&redirect_uri=" + URLEncoder.encode(returnURI, "UTF-8"); + // Debug.logInfo("LinkedIn get access token query string: " + queryString, module); + postMethod.setQueryString(queryString); + params.setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY); + postMethod.setParams(params); + jsonClient.executeMethod(postMethod); + // Debug.logInfo("LinkedIn get access token response code: " + postMethod.getStatusCode(), module); + // Debug.logInfo("LinkedIn get access token response content: " + postMethod.getResponseBodyAsString(1024), module); + if (postMethod.getStatusCode() == HttpStatus.SC_OK) { + // Debug.logInfo("Json Response from LinkedIn: " + postMethod.getResponseBodyAsString(1024), module); + JSON jsonObject = JSON.from(postMethod.getResponseBodyAsString(1024)); + JSONToMap jsonMap = new JSONToMap(); + Map<String, Object> userMap = jsonMap.convert(jsonObject); + accessToken = (String) userMap.get("access_token"); + // Debug.logInfo("Generated Access Token : " + accessToken, module); + } else { + String errMsg = UtilProperties.getMessage(resource, "GetOAuth2LinkedInAccessTokenError", UtilMisc.toMap("error", postMethod.getResponseBodyAsString()), UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + return "error"; + } + } catch (UnsupportedEncodingException e) { + request.setAttribute("_ERROR_MESSAGE_", e.toString()); + return "error"; + } catch (HttpException e) { + request.setAttribute("_ERROR_MESSAGE_", e.toString()); + return "error"; + } catch (IOException e) { + request.setAttribute("_ERROR_MESSAGE_", e.toString()); + return "error"; + } catch (ConversionException e) { + request.setAttribute("_ERROR_MESSAGE_", e.toString()); + return "error"; + } finally { + postMethod.releaseConnection(); + } + + // Get User Profile + GetMethod getMethod = new GetMethod(TokenEndpoint + UserApiUri + "?oauth2_access_token=" + accessToken); + Document userInfo = null; + try { + userInfo = LinkedInAuthenticator.getUserInfo(getMethod, UtilHttp.getLocale(request)); + } catch (HttpException e) { + request.setAttribute("_ERROR_MESSAGE_", e.toString()); + return "error"; + } catch (IOException e) { + request.setAttribute("_ERROR_MESSAGE_", e.toString()); + return "error"; + } catch (AuthenticatorException e) { + request.setAttribute("_ERROR_MESSAGE_", e.toString()); + return "error"; + } catch (SAXException e) { + request.setAttribute("_ERROR_MESSAGE_", e.toString()); + return "error"; + } catch (ParserConfigurationException e) { + request.setAttribute("_ERROR_MESSAGE_", e.toString()); + return "error"; + } finally { + getMethod.releaseConnection(); + } + // Debug.logInfo("LinkedIn User Info:" + userInfo, module); + + // Store the user info and check login the user + return checkLoginLinkedInUser(request, userInfo, accessToken); + } + + private static String checkLoginLinkedInUser(HttpServletRequest request, Document userInfo, String accessToken) { + Delegator delegator = (Delegator) request.getAttribute("delegator"); + LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher"); + String productStoreId = ProductStoreWorker.getProductStoreId(request); + String linkedInUserId = LinkedInAuthenticator.getLinkedInUserId(userInfo); + GenericValue linkedInUser = null; + try { + linkedInUser = delegator.findOne("LinkedInUser", UtilMisc.toMap("linkedInUserId", linkedInUserId), false); + } catch (GenericEntityException e) { + request.setAttribute("_ERROR_MESSAGE_", e.getMessage()); + return "error"; + } + if (UtilValidate.isNotEmpty(linkedInUser)) { + boolean dataChanged = false; + if (!accessToken.equals(linkedInUser.getString("accessToken"))) { + linkedInUser.set("accessToken", accessToken); + dataChanged = true; + } + if (!envPrefix.equals(linkedInUser.getString("envPrefix"))) { + linkedInUser.set("envPrefix", envPrefix); + dataChanged = true; + } + if (!productStoreId.equals(linkedInUser.getString("productStoreId"))) { + linkedInUser.set("productStoreId", productStoreId); + dataChanged = true; + } + if (dataChanged) { + try { + linkedInUser.store(); + } catch (GenericEntityException e) { + Debug.logError(e.getMessage(), module); + } + } + } else { + linkedInUser = delegator.makeValue("LinkedInUser", UtilMisc.toMap("accessToken", accessToken, + "productStoreId", productStoreId, + "envPrefix", envPrefix, + "linkedInUserId", linkedInUserId)); + try { + linkedInUser.create(); + } catch (GenericEntityException e) { + Debug.logError(e.getMessage(), module); + } + } + try { + GenericValue userLogin = EntityUtil.getFirst(delegator.findByAnd("UserLogin", UtilMisc.toMap("externalAuthId", linkedInUserId), null, false)); + LinkedInAuthenticator authn = new LinkedInAuthenticator(); + authn.initialize(dispatcher); + if (UtilValidate.isEmpty(userLogin)) { + String userLoginId = authn.createUser(userInfo); + userLogin = delegator.findOne("UserLogin", UtilMisc.toMap("userLoginId", userLoginId), false); + } + String password = PassportUtil.randomString(); + boolean useEncryption = "true".equals(UtilProperties.getPropertyValue("security.properties", "password.encrypt")); + userLogin.set("currentPassword", useEncryption ? HashCrypt.digestHash(LoginServices.getHashType(), null, password) : password); + userLogin.store(); + request.setAttribute("USERNAME", userLogin.getString("userLoginId")); + request.setAttribute("PASSWORD", password); + } catch (GenericEntityException e) { + Debug.logError(e.getMessage(), module); + request.setAttribute("_ERROR_MESSAGE_", e.toString()); + return "error"; + } catch (AuthenticatorException e) { + Debug.logError(e.getMessage(), module); + request.setAttribute("_ERROR_MESSAGE_", e.toString()); + return "error"; + } + return "success"; + } + + public static GenericValue getOAuth2LinkedInConfig(HttpServletRequest request) { + Delegator delegator = (Delegator) request.getAttribute("delegator"); + String productStoreId = ProductStoreWorker.getProductStoreId(request); + try { + return getOAuth2LinkedInConfig(delegator, productStoreId); + } catch (GenericEntityException e) { + Map<String, String> messageMap = UtilMisc.toMap("errorMessage", e.toString()); + String errMsg = UtilProperties.getMessage(resource, "GetOAuth2LinkedInError", messageMap, UtilHttp.getLocale(request)); + request.setAttribute("_ERROR_MESSAGE_", errMsg); + } + return null; + } + + public static GenericValue getOAuth2LinkedInConfig(Delegator delegator, String productStoreId) throws GenericEntityException { + return EntityUtil.getFirst(EntityUtil.filterByDate(delegator.findByAnd("OAuth2LinkedIn", UtilMisc.toMap("productStoreId", productStoreId), null, false))); + } +} Propchange: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/LinkedInEvents.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/LinkedInEvents.java ------------------------------------------------------------------------------ svn:keywords = Date Rev Author URL Id Propchange: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/LinkedInEvents.java ------------------------------------------------------------------------------ svn:mime-type = text/plain |
Free forum by Nabble | Edit this page |