[Python-modules-commits] [python-social-auth] 56/61: Fix Google+ auth complete, update examples with updated SDK usage. Refs #316

Wolfgang Borgert debacle at moszumanska.debian.org
Sat Dec 24 15:14:07 UTC 2016


This is an automated email from the git hooks/post-receive script.

debacle pushed a commit to tag v0.2.13
in repository python-social-auth.

commit a4918af20e09642b8ee47724a023899ef93fd22b
Author: Matías Aguirre <matiasaguirre at gmail.com>
Date:   Mon Aug 31 12:28:21 2015 -0300

    Fix Google+ auth complete, update examples with updated SDK usage. Refs #316
---
 docs/backends/google.rst                           | 118 +++++++++++++--------
 .../django_example/example/templates/home.html     |  90 ++++++++++------
 social/backends/google.py                          |  38 +++----
 3 files changed, 151 insertions(+), 95 deletions(-)

diff --git a/docs/backends/google.rst b/docs/backends/google.rst
index affe7f7..64dd66e 100644
--- a/docs/backends/google.rst
+++ b/docs/backends/google.rst
@@ -63,8 +63,9 @@ Google+ Sign-In
 done by their Javascript which thens calls a defined handler to complete the
 auth process.
 
-* To enable the backend create an application using the `Google console`_ and
-  following the steps from the `official guide`_. Make sure to enable the Google+ API in the console.
+* To enable the backend create an application using the `Google
+  console`_ and following the steps from the `official guide`_. Make
+  sure to enable the Google+ API in the console.
 
 * Fill in the key settings looking inside the Google console the subsection
   ``Credentials`` inside ``API & auth``::
@@ -81,57 +82,83 @@ auth process.
   ``SOCIAL_AUTH_GOOGLE_PLUS_SECRET`` corresponds to the variable
   ``CLIENT SECRET``.
 
-* Create a new Django view and in its template add the Google+ Sign-In button::
-
-    <div id="signinButton">
-        <span id="signinButton">
-            <span
-                class="g-signin"
-                data-callback="signInCallback"
-                data-clientid="{{ plus_id }}"
-                data-cookiepolicy="single_host_origin"
-                data-requestvisibleactions="http://schemas.google.com/AddActivity"
-                data-scope="https://www.googleapis.com/auth/plus.login">
-            </span>
-        </span>
-    </div>
-
-    <form id="google-plus" method="post" action="{% url 'social:complete' "google-plus" %}">
-        {% csrf_token %}
-        <input id="at" type="hidden" name="access_token" value="" />
-        <input id="code" type="hidden" name="code" value="" />
-    </form>
-
-  ``plus_id`` is the value from ``SOCIAL_AUTH_GOOGLE_PLUS_KEY``.
-  ``signInCallback`` is the name of your Javascript callback function.
-  If you would like to get user's email address and have it stored, then set
-  this value in `data-scope`::
-
-    data-scope="https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email"
+* Add the sign-in button to your template, you can use the SDK button
+  or add your own and attacht he click handler to it (check `Google+ Identity Sign-In`_
+  documentation about it)::
+
+    <div id="google-plus-button">Google+ Sign In</div>
 
 * Add the Javascript snippet in the same template as above::
 
-    <script src="//code.jquery.com/jquery-1.11.2.min.js"></script>
+    <script src="https://apis.google.com/js/api:client.js"></script>
+
     <script type="text/javascript">
-    (function() {
-        var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
-        po.src = 'https://apis.google.com/js/client:plusone.js';
-        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
-    })();
+      gapi.load('auth2', function () {
+        var auth2;
+
+        auth2 = gapi.auth2.init({
+          client_id: "<PUT SOCIAL_AUTH_GOOGLE_PLUS_KEY HERE>",
+          scope: "<PUT BACKEND SCOPE HERE>"
+        });
+
+        auth2.then(function () {
+          var button = document.getElementById("google-plus-button");
+          console.log("User is signed-in in Google+ platform?", auth2.isSignedIn.get() ? "Yes" : "No");
+
+          auth2.attachClickHandler(button, {}, function (googleUser) {
+            // Send access-token to backend to finish the authenticate
+            // with your application
+
+            var authResponse = googleUser.getAuthResponse();
+            var $form;
+            var $input;
+
+            $form = $("<form>");
+            $form.attr("action", "/complete/google-plus");
+            $form.attr("method", "post");
+            $input = $("<input>");
+            $input.attr("name", "access_token");
+            $input.attr("value", authResponse.access_token);
+            $form.append($input);
+            // Add csrf-token if needed
+            $(document.body).append($form);
+            $form.submit();
+          });
+        });
+      });
     </script>
+    {% endif %}
+
+* Logging out
 
-* And define your Javascript callback function::
+  Logging-out can be tricky when using the the platform SDK because it
+  can trigger an automatic sign-in when listening to the user status
+  change. With the method show above, that won't happen, but if the UI
+  depends more in the SDK values than the backend, then things can get
+  out of sync easilly. To prevent this, the user should be logged-out
+  from Google+ platform too. This can be accomplished by doing::
 
     <script type="text/javascript">
-    var signInCallback = function (result) {
-        if (result['error']) {
-            alert('An error happened:', result['error']);
-        } else {
-            $('#code').attr('value', result['code']);
-            $('#at').attr('value', result['access_token']);
-            $('#google-plus').submit();
-        }
-    };
+      gapi.load('auth2', function () {
+        var auth2;
+
+        auth2 = gapi.auth2.init({
+          client_id: "{{ plus_id }}",
+          scope: "{{ plus_scope }}"
+        });
+
+        auth2.then(function () {
+          if (auth2.isSignedIn.get()) {
+            $('#logout').on('click', function (event) {
+              event.preventDefault();
+              auth2.signOut().then(function () {
+                console.log("Logged out from Google+ platform");
+                document.location = "/logout";
+              });
+            });
+          }
+        });
+      });
     </script>
 
 
@@ -223,3 +250,4 @@ supporting them you can default to the old values by defining this setting::
 .. _official guide: https://developers.google.com/+/web/signin/#step_1_create_a_client_id_and_client_secret
 .. _Sept 1, 2014: https://developers.google.com/+/api/auth-migration#timetable
 .. _e3525187: https://github.com/omab/python-social-auth/commit/e35251878a88954cecf8e575eca27c63164b9f67
+.. _Google+ Identity Sign-In: https://developers.google.com/identity/sign-in/web/sign-in
diff --git a/examples/django_example/example/templates/home.html b/examples/django_example/example/templates/home.html
index 3a51c59..58b7ec8 100644
--- a/examples/django_example/example/templates/home.html
+++ b/examples/django_example/example/templates/home.html
@@ -11,7 +11,7 @@
       .col-md-2 { width: 18.6667%; }
       .buttons { display: block; table-layout: fixed; border-radius: 7px; border: 1px solid #ccc;
                  margin: 20px; background: #eee; padding: 30px; }
-      .buttons > div a { margin: 5px 10px; }
+      .buttons > div .btn { margin: 5px 10px; }
       .buttons > div:not(:first-child) { margin-top: 10px; border-top: 1px solid #ccc;
                                          padding-top: 10px; text-align: center; }
       .user-details { text-align: center; font-size: 16px; font-weight: bold; }
@@ -35,17 +35,24 @@
             {% for name, backend in sublist %}
               {% associated backend %}
               {% if association %}
-                <form class="disconnect-form col-md-2" action="{% url "social:disconnect_individual" backend=association.provider association_id=association.id %}" method="post">{% csrf_token %}
+                <form class="disconnect-form col-md-2" id="{{ name }}-disconnect" action="{% url "social:disconnect_individual" backend=association.provider association_id=association.id %}" method="post">{% csrf_token %}
                   <a class="btn btn-danger" name="{{ backend|backend_class }}" href="#">
                     <i class="fa fa-{{ name|icon_name }}"></i>
                     Disconnect {{ backend|backend_name }}
                   </a>
                 </form>
               {% else %}
-                <a class="col-md-2 btn btn-default" name="{{ backend|backend_class }}" href="{% url "social:begin" backend=name %}">
-                  <i class="fa fa-{{ name|icon_name }}"></i>
-                  {{ backend|backend_name }}
-                </a>
+                {% if name == "google-plus" %}
+                  <div class="col-md-2 btn btn-default" id="{{ name }}-button" name="{{ backend|backend_class }}">
+                    <i class="fa fa-{{ name|icon_name }}"></i>
+                    {{ backend|backend_name }}
+                  </div>
+                {% else %}
+                  <a class="col-md-2 btn btn-default" id="{{ name }}-button" name="{{ backend|backend_class }}" href="{% url "social:begin" backend=name %}">
+                    <i class="fa fa-{{ name|icon_name }}"></i>
+                    {{ backend|backend_name }}
+                  </a>
+                {% endif %}
               {% endif %}
             {% endfor %}
           </div>
@@ -77,7 +84,7 @@
       </div>
 
       <div>
-        <a class="btn btn-primary" href="/logout/">
+        <a class="btn btn-primary" href="/logout/" id="logout">
           <i class="fa fa-sign-out"></i>
           Logout
         </a>
@@ -322,38 +329,57 @@
     </div>
 
     {% if plus_id %}
-    <form id="google-plus" method="post" action="{% url "social:complete" backend="google-plus" %}">{% csrf_token %}
-      <input id="at" type="hidden" name="access_token" value="" />
-      <input id="code" type="hidden" name="code" value="" />
-
-      <div id="signinButton">
-        <span class="g-signin" data-scope="{{ plus_scope }}"
-                               data-clientid="{{ plus_id }}"
-                               data-redirecturi="postmessage"
-                               data-accesstype="offline"
-                               data-cookiepolicy="single_host_origin"
-                               data-callback="signInCallback">
-        </span>
-      </div>
-    </form>
+    <script src="https://apis.google.com/js/api:client.js"></script>
+    <script type="text/javascript">
+        gapi.load('auth2', function () {
+          var auth2;
+
+          auth2 = gapi.auth2.init({
+            client_id: "{{ plus_id }}",
+            scope: "{{ plus_scope }}"
+          });
+
+          auth2.then(function () {
+            var button = document.getElementById("google-plus-button");
+            console.log("User is signed-in in Google+ platform?", auth2.isSignedIn.get() ? "Yes" : "No");
+
+            if (button) {
+              auth2.attachClickHandler(button, {}, function (googleUser) {
+                var authResponse = googleUser.getAuthResponse();
+                var $form;
+                var $input;
+
+                $form = $("<form>");
+                $form.attr("action", "{% url "social:complete" backend="google-plus" %}");
+                $form.attr("method", "post");
+                $input = $("<input>");
+                $input.attr("name", "access_token");
+                $input.attr("value", authResponse.access_token);
+                $form.append($input);
+                $form.append("{% csrf_token %}");
+                $(document.body).append($form);
+                $form.submit();
+              });
+            } else if (auth2.isSignedIn.get()) {
+              $('#logout').on('click', function (event) {
+                event.preventDefault();
+
+                auth2.signOut().then(function () {
+                  console.log("Logged out from Google+ platform");
+                  document.location = $(event.target).attr('href');
+                });
+              });
+            }
+          });
+        });
+    </script>
     {% endif %}
 
     <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
     <script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
-    <script src="https://plus.google.com/js/client:plusone.js?onload=start" type="text/javascript"></script>
     <script src="https://login.persona.org/include.js" type="text/javascript"></script>
 
     <script type="text/javascript">
-      var signInCallback = function (result) {
-          if (result['error']) {
-            alert('An error happened:', result['error']);
-          } else {
-            $('#code').attr('value', result['code']);
-            $('#at').attr('value', result['access_token']);
-            $('#google-plus').submit();
-          }
-      };
-
       var modalDialog = function (modalId, modalLinkName, submitHandler) {
         var $modal;
 
diff --git a/social/backends/google.py b/social/backends/google.py
index bc37d2d..8affe6d 100644
--- a/social/backends/google.py
+++ b/social/backends/google.py
@@ -113,6 +113,7 @@ class GooglePlusAuth(BaseGoogleOAuth2API, BaseOAuth2):
     REVOKE_TOKEN_METHOD = 'GET'
     DEFAULT_SCOPE = [
         'https://www.googleapis.com/auth/plus.login',
+        'https://www.googleapis.com/auth/plus.me',
     ]
     DEPRECATED_DEFAULT_SCOPE = [
         'https://www.googleapis.com/auth/plus.login',
@@ -136,26 +137,27 @@ class GooglePlusAuth(BaseGoogleOAuth2API, BaseOAuth2):
 
     @handle_http_errors
     def auth_complete(self, *args, **kwargs):
-        if 'access_token' in self.data and 'code' not in self.data:
-            raise AuthMissingParameter(self, 'access_token or code')
-
-        # Token won't be available in plain server-side workflow
-        token = self.data.get('access_token')
-        if token:
-            self.process_error(self.get_json(
+        if 'access_token' in self.data:  # Client-side workflow
+            token = self.data.get('access_token')
+            response = self.get_json(
                 'https://www.googleapis.com/oauth2/v1/tokeninfo',
                 params={'access_token': token}
-            ))
-
-        response = self.request_access_token(
-            self.ACCESS_TOKEN_URL,
-            data=self.auth_complete_params(),
-            headers=self.auth_headers(),
-            method=self.ACCESS_TOKEN_METHOD
-        )
-        self.process_error(response)
-        return self.do_auth(response['access_token'], response=response,
-                            *args, **kwargs)
+            )
+            self.process_error(response)
+            return self.do_auth(token, response=response, *args, **kwargs)
+        elif 'code' in self.data:  # Server-side workflow
+            response = self.request_access_token(
+                self.ACCESS_TOKEN_URL,
+                data=self.auth_complete_params(),
+                headers=self.auth_headers(),
+                method=self.ACCESS_TOKEN_METHOD
+            )
+            self.process_error(response)
+            return self.do_auth(response['access_token'],
+                                response=response,
+                                *args, **kwargs)
+        else:
+            raise AuthMissingParameter(self, 'access_token or code')
 
 
 class GoogleOAuth(BaseGoogleAuth, BaseOAuth1):

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-social-auth.git



More information about the Python-modules-commits mailing list