Full Code of shashi278/social-auth-kivy for AI

master 0dee71933953 cached
32 files
33.0 MB
18.0k tokens
92 symbols
1 requests
Download .txt
Repository: shashi278/social-auth-kivy
Branch: master
Commit: 0dee71933953
Files: 32
Total size: 33.0 MB

Directory structure:
gitextract_31w1vpdd/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   └── workflows/
│       └── python-publish.yml
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── demo/
│   ├── bin/
│   │   └── glogin__armeabi-v7a-0.1-armeabi-v7a-debug.apk
│   ├── intents.xml
│   └── main.py
├── docs/
│   ├── integrate-firebase-auth.md
│   ├── integrate-google-facebook-login.md
│   └── prerequisites.md
├── kivyauth/
│   ├── __init__.py
│   ├── android/
│   │   ├── __init__.py
│   │   ├── facebook_auth.py
│   │   ├── firebase_auth.py
│   │   ├── github_auth.py
│   │   ├── google_auth.py
│   │   └── twitter_auth.py
│   ├── desktop/
│   │   ├── __init__.py
│   │   ├── facebook_auth.py
│   │   ├── github_auth.py
│   │   ├── google_auth.py
│   │   ├── twitter_auth.py
│   │   └── utils.py
│   ├── facebook_auth.py
│   ├── github_auth.py
│   ├── google_auth.py
│   ├── twitter_auth.py
│   └── utils.py
└── setup.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Desktop (please complete the following information):**
 - OS: [e.g. iOS]

**Smartphone (please complete the following information):**
 - Device: [e.g. Samsung M30]
 - OS: [e.g. Android 10]

**Additional context**
Add any other context about the problem here.


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.


================================================
FILE: .github/workflows/python-publish.yml
================================================
# This workflow will upload a Python Package using Twine when a release is created
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

name: Upload Python Package

on:
  release:
    types: [published]

permissions:
  contents: read

jobs:
  deploy:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - name: Set up Python
      uses: actions/setup-python@v3
      with:
        python-version: '3.x'
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install build
    - name: Build package
      run: python -m build
    - name: Publish package
      uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
      with:
        user: __token__
        password: ${{ secrets.PYPI_API_TOKEN }}


================================================
FILE: .gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# pipenv
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
#   having no cross-platform support, pipenv may install dependencies that don't work, or not
#   install all needed dependencies.
#Pipfile.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
.buildozer
.vscode

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/


================================================
FILE: .travis.yml
================================================
cache: pip
matrix:
  fast_finish: true
  include:
  - name: Black
    env: RUN=black
    language: python
    python: 3.7
    os: linux
    dist: bionic
install:
- pip install pycodestyle
script:
- pycodestyle kivyauth/android/__init__.py
after_failure:
- sleep 10;
- echo == End ==
deploy:
  skip_existing: true
  provider: pypi
  user: __token__
  password:
    secure: HDX4vTR4+shTPAc2+SPOE5Z+/5eZkvlX0JtDY+UniEbdSUougWxS1Z+TxWSlQQyL1LE0wB3Wxt1EimBYPDgKu+AiIhSXkjonGvnD4txXTV1qolDOudNzWndu+yPc2AnZi8eWaRGE+s7cJjWVeW7ddCZGfCS2WycSLz3MtGXJfPOz4bB+UhAWc+uAj8VBu72ZeyU8QFRvYgCbeHVAhFcx4U1t6gju601/n3eoylJsUb4Dx/ssCARMplHjW81MvGCX7jbuBadB/mOoo7FdQ42PCzPtDIxeyORR8T6gKcWWga+IWswf8bWau//ry/walbWWqegIam7XeXQK8a1nDMqGGJ0Sn4J5jpJS8wVnmK6Dtw6VALtmPTUd+S7p1pnaDCvEF79zv33qowrVbe4hgHPsX+RWHVs1Vkv2MJ+WtUoDuQizeK7pi+DIpDkHXSZCZRSd2m1pDEz51DjDhKJVJfKmuypIaf2yRtiNpnJgtqfSC9Hk+ErcZW9C311oyFzHIvTlYjlQfepfl3cUImwBoj6FTIUPovLbnn6eXh6k45GltBLG5mOt8nWpFvhHDNf+kcCotyqxTpS46a5p0p4rpsURELSXLsCUely1g1xqEkXLWVeu793qBZweyahiAp9iH+gx+za8xjip5Rty5uUxITuPbv1ITU6nEshQKvbrNfwwALA=
  distributions: sdist bdist_wheel
  on:
    tags: true


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2020 Shashi Ranjan

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
<p align="center"> <img src="https://raw.githubusercontent.com/shashi278/social-auth-kivy/master/demo/kivyauth_logo.png" width="30%" ></img> </p>


# KivyAuth
#### *Integrate Google, Facebook, Github &amp; Twitter login in kivy applications*
[![build](https://travis-ci.org/shashi278/social-auth-kivy.svg?branch=master)](https://travis-ci.org/github/shashi278/social-auth-kivy/) [![Python 3.6](https://img.shields.io/pypi/pyversions/kivymd)](https://www.python.org/downloads/release/python-360/) [![pypi](https://img.shields.io/pypi/v/kivyauth)](https://pypi.org/project/KivyAuth/) [![license](https://img.shields.io/pypi/l/kivyauth)](https://github.com/shashi278/social-auth-kivy/blob/master/LICENSE) [![format](https://img.shields.io/pypi/format/kivyauth)](https://pypi.org/project/KivyAuth/#modal-close) [![downloads](https://img.shields.io/pypi/dm/kivyauth)](https://pypi.org/project/KivyAuth/) [![code size](https://img.shields.io/github/languages/code-size/shashi278/social-auth-kivy)]() [![repo size](https://img.shields.io/github/repo-size/shashi278/social-auth-kivy)]()

### KivyAuth on Android
![Demo Gif](https://raw.githubusercontent.com/shashi278/social-auth-kivy/master/demo/demo.gif)

<a href='https://play.google.com/store/apps/details?id=com.watney.glogin' ><img src='https://raw.githubusercontent.com/steverichey/google-play-badge-svg/266d2b2df26f10d3c00b8129a0bd9f6da6b19f00/img/en_get.svg' alt='Get it on Playstore' width=200/> </a>

##
### KivyAuth on Desktop
![Desktop_demo_test gif](https://raw.githubusercontent.com/shashi278/social-auth-kivy/cross-platform/demo/kivyauth_desktop_alpha.gif)


### Run [demo](demo/) app on desktop:
 * **Make Sure you've created OAuth apps and have their CLIENT_ID and CLIENT_SECRET handy before running demo application**
 * Create an .env file in the app directory with below format:
  ```properties
  GOOGLE_CLIENT_ID=<Your-client-id-from-google-cloud-console>
  GOOGLE_CLIENT_SECRET=<Your-Client-Secret>

  FACEBOOK_CLIENT_ID=<Your-Facebook-Client-id>
  FACEBOOK_CLIENT_SECRET=<Your-Facebook-Client-secret>

  GITHUB_CLIENT_ID=<Github-Client-id>
  GITHUB_CLIENT_SECRET=<Github-Client-secret>

  ```

##
## How to use

### Instruction for using KivyAuth on Desktop:
* pip install kivyauth==2.3.3

### Note for android:
  Make sure you go through the [prerequisites](https://github.com/shashi278/social-auth-kivy/blob/master/docs/prerequisites.md)
  for the login methods you're going to integrate in your application before moving further

#
The example below shows integrating google login. Similarly other login methods can also be used.

* Include necessary imports for google login
```python
from kivyauth.google_auth import initialize_google, login_google, logout_google
```

* Initialize google login inside your app's build method
```python
def build(self):
  initialize_google(self.after_login, self.error_listener)
```
`after_login` is a function to be called upon successful login with `name`, `email`, and `photo url` of the user. So, create a success listener function which accepts three parameters and perform after-login stuffs(like updating UI, etc.). `error_listener` is called in case of any error and it doesn't accept any argument.

* You can also add auto-login( if the user is already logged in then directly move to after-login stuff) inside app's `on_start` method as below(mention only login providers you are using in your app):
```python
def on_start(self):

    if auto_login(login_providers.google):
        self.current_provider = login_providers.google
    elif auto_login(login_providers.facebook):
        self.current_provider = login_providers.facebook
    elif auto_login(login_providers.github):
        self.current_provider = login_providers.github
    elif auto_login(login_providers.twitter):
        self.current_provider = login_providers.twitter
```

* Next, call `login_google()` upon a button click to initiate login process.

* Similarly, to logout, call `logout_google` as
```python
logout_google(self.after_logout)
```
`after_logout` is a function to be called after user gets logged out. For example, to update UI.

* Make sure to include `kivyauth` as a requirement in the buildozer.spec file
```spec
requirements = python3,kivy,kivyauth==2.3.3
```


##  
### TODO:
  * Support iOS

##
### Changelog
#### v2.3.3
  *  Fixed werkzeug server not shutting down


#### v2.3.2
  *  Fixed crashing when user doesn't have a photo


#### v2.3.1 - KivyAuth cross-platform
  * Kivyauth APIs are now platform-independent
  * Desktop support for linux, win and possibly mac


#### v2.3 - KivyAuth cross-platform
  * Desktop support added(in alpha)
  * All android auths are inside `kivyauth.android` while those for desktops are inside `kivyauth.desktop`


#### v2.2
  * Added Auto-login feature
  * `login_providers` are now inside `kivyauth` rather than `kivyauth.providers`


#### v2.0
  * Individual login providers are moved into respective folders
  * Fix problem of not being able to use individual login methods
  * Now it's relatively easier to use the library

### Other
![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)

**Contributing**: Contributions are more than welcome. Looking for contributions in making it cross-platform(specifically for iOS) and better documentation.


Feel free to ping me or raise an issue if you want to talk about this project or Kivy in general.


================================================
FILE: demo/bin/glogin__armeabi-v7a-0.1-armeabi-v7a-debug.apk
================================================
[File too large to display: 32.9 MB]

================================================
FILE: demo/intents.xml
================================================
<intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="fb439926446854840" />
        </intent-filter>

================================================
FILE: demo/main.py
================================================
import os
from dotenv import load_dotenv

from kivy.lang.builder import Builder
from kivy.metrics import dp
from kivy.uix.image import AsyncImage
from kivy.uix.screenmanager import Screen
from kivy.uix.boxlayout import BoxLayout
from kivy import platform
from kivy.clock import Clock
from kivymd.app import MDApp
from kivymd.uix.button import MDRectangleFlatIconButton
from kivymd.uix.snackbar import Snackbar
from kivymd.uix.behaviors.elevation import CommonElevationBehavior

from kivyauth.google_auth import initialize_google, login_google, logout_google
from kivyauth.facebook_auth import initialize_fb, login_facebook, logout_facebook
from kivyauth.github_auth import initialize_github, login_github, logout_github
from kivyauth.twitter_auth import initialize_twitter, login_twitter, logout_twitter
from kivyauth.utils import stop_login
from kivyauth.utils import login_providers, auto_login

load_dotenv()

if platform == "android":
    from android.runnable import run_on_ui_thread
    from jnius import autoclass, cast

    Toast = autoclass("android.widget.Toast")
    String = autoclass("java.lang.String")
    CharSequence = autoclass("java.lang.CharSequence")
    Intent = autoclass("android.content.Intent")
    Uri = autoclass("android.net.Uri")
    NewRelic = autoclass("com.newrelic.agent.android.NewRelic")
    LayoutParams = autoclass("android.view.WindowManager$LayoutParams")
    AndroidColor = autoclass("android.graphics.Color")

    PythonActivity = autoclass("org.kivy.android.PythonActivity")

    context = PythonActivity.mActivity

    @run_on_ui_thread
    def show_toast(text):
        t = Toast.makeText(
            context, cast(CharSequence, String(text)), Toast.LENGTH_SHORT
        )
        t.show()

    @run_on_ui_thread
    def set_statusbar_color():
        window = context.getWindow()
        window.addFlags(LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
        window.setStatusBarColor(AndroidColor.TRANSPARENT)


kv = """
#:import Clock kivy.clock.Clock
#:import platform kivy.platform
ScreenManager:
    
    LoginScreen:
        id: login_screen
    
    HomeScreen:
        id: home_screen

<LoginScreen>:
    name:"loginscreen"
    BoxLayout:
        orientation:"vertical"

        MDTopAppBar:
            title: "KivyAuth Demo"
            elevation:9
            opposite_colos: True
            left_action_items: [['menu', lambda x: None]]
            right_action_items: [['source-fork', lambda x: app.send_to_github()]]

        BoxLayout:
            orientation:"vertical"

            Widget:
                size_hint_y: None
                height: dp(100)

            LoginButton
                text: "Sign In with Google"
                icon: "google"
                text_color: 1,1,1,1
                can_color: 66/255, 133/255, 244/255, 1
                release_action: app.gl_login
            
            LoginButton
                text: "Sign In with Facebook"
                icon: "facebook"
                text_color: 1,1,1,1
                can_color: 59/255, 89/255, 152/255, 1
                release_action: app.fb_login
            
            LoginButton
                text: "Sign In with Github"
                icon: "github-circle" if platform == "android" else  "github"
                text_color: 1,1,1,1
                can_color: 33/255, 31/255, 31/255, 1
                release_action: app.git_login
            
            LoginButton
                text: "Sign In with Twitter"
                icon: "twitter"
                text_color: 1,1,1,1
                can_color: 8/255, 160/255, 233/255, 1
                release_action: app.twitter_login
            
            Widget:
                size_hint_y: None
                height: dp(100)

<LoginButton@AnchorLayout>:
    text:""
    icon: ""
    text_color: [0,0,0,1]
    can_color: 1,1,1,1
    release_action: print
    RectangleRaisedIconButton:
        width: dp(270)
        height: dp(50)
        canvas.before:
            Color:
                rgba: root.can_color
            Rectangle:
                pos: self.pos
                size: self.size
        

        elevation: 8
        icon: root.icon
        text: root.text
        font_size: dp(8) if platform == "android" else dp(18)
        text_color: root.text_color
        on_release:
            if root.release_action: Clock.schedule_once(root.release_action, 0)
        

<HomeScreen@Screen>:
    name:"homescreen"

    BoxLayout:
        id: main_box
        orientation:"vertical"

        MDTopAppBar:
            id: user_name
            title: ""
            elevation: 9
            opposite_colos: True
            left_action_items: [['menu', lambda x: None]]
            right_action_items: [['information-outline', lambda x: None]]
        
        AnchorLayout:
            id: user_photo

        BoxLayout:
            size_hint_y:None
            height: dp(20)
            padding: dp(5)
            
            MDLabel:
                id: user_email
                halign: "center"
                font_style: "Body1"
                text: ""

        AnchorLayout:
            MDRaisedButton:
                text: "LOGOUT"
                md_bg_color: .9,.9,.9,1
                theme_text_color: "Custom"
                text_color: 0,0,0,1
                on_release:
                    app.logout_()


<Content>:
    orientation: "vertical"
    size_hint_y: None
    height: "90dp"

    AnchorLayout:
        MDSpinner:
            size_hint: None, None
            size: dp(30), dp(30)
            pos_hint: {'center_x': .5, 'center_y': .5}
    
    AnchorLayout:
        MDLabel:
            text: "Logging in..."
            halign: "center"
"""

class Content(BoxLayout):
    pass

class Content(BoxLayout):
    pass


class LoginScreen(Screen):
    pass


class RectangleRaisedIconButton(
    MDRectangleFlatIconButton, CommonElevationBehavior
):
    pass


class LoginDemo(MDApp):
    current_provider = ""

    def build(self):
        initialize_google(
            self.after_login,
            self.error_listener,
            os.getenv("GOOGLE_CLIENT_ID"),
            os.getenv("GOOGLE_CLIENT_SECRET"),
        )
        initialize_fb(
            self.after_login,
            self.error_listener,
            os.getenv("FACEBOOK_CLIENT_ID"),
            os.getenv("FACEBOOK_CLIENT_SECRET"),
        )
        initialize_github(
            self.after_login,
            self.error_listener,
            os.getenv("GITHUB_CLIENT_ID"),
            os.getenv("GITHUB_CLIENT_SECRET"),
        )

        if platform == "android":
            set_statusbar_color()
        tmp = Builder.load_string(kv)
        if platform != "android":
            from kivymd.uix.dialog import MDDialog
            from kivymd.uix.button import MDFlatButton

            btn = MDFlatButton(text="CANCEL", text_color=self.theme_cls.primary_color)
            btn.bind(on_release=lambda *args: (stop_login(), self.dialog.dismiss()))
            self.dialog = MDDialog(
                title="",
                size_hint_x=None,
                size_hint_y=None,
                width="250dp",
                type="custom",
                auto_dismiss=False,
                content_cls=Content(),
                buttons=[btn],
            )
        return tmp

    def on_start(self):
        if platform == "android":
            if auto_login(login_providers.google):
                self.current_provider = login_providers.google
            elif auto_login(login_providers.facebook):
                self.current_provider = login_providers.facebook
            elif auto_login(login_providers.github):
                self.current_provider = login_providers.github
            elif auto_login(login_providers.twitter):
                self.current_provider = login_providers.twitter
            primary_clr= [ 108/255, 52/255, 131/255 ]
            hex_color= '#%02x%02x%02x' % (int(primary_clr[0]*200), int(primary_clr[1]*200), int(primary_clr[2]*200))
            set_statusbar_color()
        pass

    def show_login_progress(self):
        if platform != "android":
            self.dialog.open()

    def hide_login_progress(self):
        if platform != "android":
            self.dialog.dismiss()

    def fb_login(self, *args):
        login_facebook()
        self.current_provider = login_providers.facebook
        self.show_login_progress()

    def gl_login(self, *args):
        login_google()
        self.current_provider = login_providers.google
        self.show_login_progress()

    def git_login(self, *args):
        login_github()
        self.current_provider = login_providers.github
        self.show_login_progress()

    def twitter_login(self, *args):
        login_twitter()
        self.current_provider = login_providers.twitter
        self.show_login_progress()

    def logout_(self):
        if self.current_provider == login_providers.google:
            logout_google(self.after_logout)
        if self.current_provider == login_providers.facebook:
            logout_facebook(self.after_logout)
        if self.current_provider == login_providers.github:
            logout_github(self.after_logout)
        if self.current_provider == login_providers.twitter:
            logout_twitter(self.after_logout)

    def after_login(self, name, email, photo_uri):
        self.hide_login_progress()

        if platform == "android":
            show_toast("Logged in using {}".format(self.current_provider))
        else:
            Snackbar(text="Logged in using {}".format(self.current_provider)).open()

        self.root.current = "homescreen"
        self.update_ui(name, email, photo_uri)

    def after_logout(self):
        self.update_ui("", "", "")
        self.root.current = "loginscreen"
        if platform == "android":
            show_toast(text="Logged out from {} login".format(self.current_provider))
        else:
            Snackbar(
                text="Logged out from {} login".format(self.current_provider)
            ).open()

    def update_ui(self, name, email, photo_uri):
        self.root.ids.home_screen.ids.user_photo.add_widget(
            AsyncImage(
                source=photo_uri, size_hint=(None, None), height=dp(60), width=dp(60)
            )
        )
        self.root.ids.home_screen.ids.user_name.title = "Welcome, {}".format(name)
        self.root.ids.home_screen.ids.user_email.text = (
            "Your Email: {}".format(email)
            if email
            else "Your Email: Could not fetch email"
        )

    def error_listener(self):
        if platform == "android":
            show_toast("Error logging in.")
        else:
            Snackbar(text="Error logging in. Check connection or try again.").show()
        Clock.schedule_once(lambda *args: self.hide_login_progress())

    def send_to_github(self):
        if platform == "android":
            intent = Intent()
            intent.setAction(Intent.ACTION_VIEW)
            intent.setData(Uri.parse("https://github.com/shashi278/social-auth-kivy"))

            context.startActivity(intent)
        else:
            import webbrowser
            webbrowser.open("https://github.com/shashi278/social-auth-kivy")


if __name__ == "__main__":
    LoginDemo().run()


================================================
FILE: docs/integrate-firebase-auth.md
================================================
### Integrate Github and Twitter Login in Kivy Applications

#### Firebase has been used to integrate Github and Twitter logins

##### Prerequisites
* Declare Firebase as a gradle dependency in your `buildozer.spec` file:
 ```spec
 android.gradle_dependencies = com.google.firebase:firebase-auth:19.3.1
 ```
* For using firebase in kivy applications, we need to tweak few settings internally:
  * Build your application once, doesn't matter if it crashes
  * Then find *build.tmpl.gradle* inside *.buildozer/android/platform/build-armeabi-v7a/dists/app-name__armeabi-v7a/templates/* and change gradle plugin version from 3.1.4 to 3.5.2(I've already created a PR for the same in p4a. Hope they merge it) and add google-services plugin as it's required by firebase and apply the plugin:
  ```java
  buildscript {
    repositories {
       //...
    }
    dependencies {
        //make sure its 3.5.2 here instead of 3.1.4 
        classpath 'com.android.tools.build:gradle:3.5.2'
        
        //google-services plugin, required by firebase
        classpath 'com.google.gms:google-services:4.3.3'
    }
  }
  
  //...
  
  // At the bottom
  apply plugin: 'com.google.gms.google-services'
  ```
  * Make sure gradle version is set to latest(6.4.1) inside *gradle-wrapper.properties*(It's been updated in develop branch. If you're using master branch of p4a, you may need to update it manually). This file is located at: *.buildozer/android/platform/build-armeabi-v7a/dists/app-name__armeabi-v7a/gradle/wrapper/*
  
  * Copy your *google-services.json* inside *.buildozer/android/platform/build-armeabi-v7a/dists/app-name__armeabi-v7a/*. Its required for firebase authentication.

##### Start Integrating
  * Feel free to look at their [docs](https://firebase.google.com/docs/auth/android/start) for more.
  * Add few required java classes for firebase authentication
  ```python
  #----Firebase classes for Github and Twitter Login----#
  FirebaseAuth= autoclass('com.google.firebase.auth.FirebaseAuth')
  FirebaseApp = autoclass('com.google.firebase.FirebaseApp')
  OAuthProvider = autoclass('com.google.firebase.auth.OAuthProvider')
  FirebaseUser = autoclass('com.google.firebase.auth.FirebaseUser')
  ```
  * We need to implement two java classes to handle success and failure while logging in.
  ```python
    class OnSuccessListener(PythonJavaClass):
      __javainterfaces__=['com/google/android/gms/tasks/OnSuccessListener']
      __javacontext__= 'app'

      @java_method('(Ljava/lang/Object;)V')
      def onSuccess(self, result):
          # User is signed in
          # You may get user information like name,email, etc. now and perform after-login stuffs.
          user = FirebaseAuth.getInstance().getCurrentUser()

          # user.getDisplayName()
          # user.getEmail()
          # user.getPhotoUrl().toString()

    class OnFailureListener(PythonJavaClass):
        __javainterfaces__=['com/google/android/gms/tasks/OnFailureListener']
        __javacontext__= 'app'

        @java_method('(Ljava/lang/Exception;)V')
        def onFailure(self, e):
            #handle exception
  ```
  
  * Next, get an instance of `FirebaseAuth` inside `build` method of your app:
  ```python
    self.mAuth= FirebaseAuth.getInstance()
  ```
  * Finally, add below codes to start login process inside a method to be called when user clicks the login button:
  ```python
    provider = OAuthProvider.newBuilder("github.com") # "twitter.com" for twitter login
    pendingResultTask = FirebaseAuth.getPendingAuthResult()
    if pendingResultTask:
        #There's something already here! Finish the sign-in for your user.
        task= pendingResultTask.addOnSuccessListener(OnSuccessListener())
        task= task.addOnFailureListener(OnFailureListener())
    else:
        #There's no pending result so you need to start the sign-in flow.

        task= FirebaseAuth.startActivityForSignInWithProvider(context, provider.build())
        task= task.addOnSuccessListener(OnSuccessListener())
        task= task.addOnFailureListener(OnFailureListener())
  ```
  


================================================
FILE: docs/integrate-google-facebook-login.md
================================================
## Integrate Google and Facebook Login in Kivy Applications

##
### Google Login:

#### Prerequisite
 * Declare Google Play services as a gradle dependency in your `buildozer.spec` file:
 ```spec
 android.gradle_dependencies = com.google.android.gms:play-services-auth:18.0.0
 ```

#### Start Integrating
 * Feel free to look at their [doc](https://developers.google.com/identity/sign-in/android/sign-in) for more info
 * Add java classes required for google authentication in your `.py` file:
 ```python
 #----Java Classes For Google Login----#
 Gso= autoclass('com.google.android.gms.auth.api.signin.GoogleSignInOptions')
 GsoBuilder= autoclass('com.google.android.gms.auth.api.signin.GoogleSignInOptions$Builder')
 GSignIn= autoclass('com.google.android.gms.auth.api.signin.GoogleSignIn')
 ApiException= autoclass('com.google.android.gms.common.api.ApiException')
 ```
 * Create instance of `GoogleSignInClient` inside `build` method of your kivy App:
 ```python
 gso= GsoBuilder(Gso.DEFAULT_SIGN_IN).requestEmail().build()
 self.mGSignInClient= GSignIn.getClient(context, gso)
 ```
   Make sure you've,
 ```python
 PythonActivity= autoclass('org.kivy.android.PythonActivity')
 context= PythonActivity.mActivity
 ```
 * After the user signs in, you can get a `GoogleSignInAccount` object for the user in the activity's `onActivityResult` method.
   For this, we need to bind our function we want to be called when `onActivityResult` gets called during authentication. We can
   bind our function using bind function from android.activity as:
   ```python
   from android.activity import bind as result_bind
   
   # inside build method
   result_bind(on_activity_result=activity_listener_google)
   ```
 * Create your activity listener function:
 ```python
 def activity_listener_google(request_code, result_code, data):
    if request_code == RC_SIGN_IN:
        task= GSignIn.getSignedInAccountFromIntent(data)
        try:
            account= task.getResult(ApiException)
            if account:
                #user is logged in
                #Do stuffs you want after a user gets authenticated
                #eg. update UI, change screen, etc.
            
            else:
                #unable to get account

        except Exception as e:
            #Error in signing in
            
 ```
 `RC_SIGN_IN` is just a unique request code used to differentiate among different requests passed to `onActivityResult`. Define it an
 integer constant.
 
 * Finally, start sign in process when user clicks a button. Create a function in your `App` class to be called upon clicking login
  button and include below codes:
 ```python
 signInIntent= self.mGSignInClient.getSignInIntent()
 context.startActivityForResult(signInIntent, RC_SIGN_IN)
 
 ```
 
##

### Facebook Login:

#### Prerequisite
* We'll be creating our own version of facebook login i.e. using python and kivy by following each step from their [doc](https://developers.facebook.com/docs/facebook-login/android/). So, open it in a new tab and follow it along-side.

#### Start Integrating
* Follow their instructions in step 1 and create an OAuth App. You may skip step 2.

* For step 3, add Facebook-login SDK as a gradle dependency in your `buildozer.spec` file:
 ```spec
 android.gradle_dependencies = com.facebook.android:facebook-login:7.0.0
 ```

* For 4th step,
  * Add `INTERNET` permission in `buildozer.spec` file
    ```spec
    android.permissions = INTERNET
    ```
  * Find `android.meta_data` in buildozer.spec file and make it to look like
    ```spec
    android.meta_data = com.facebook.sdk.ApplicationId=fb<App-ID-of-your-OAuth-App>
    ```
  * Next, find `android.add_activities` in buildozer.spec file and add some activity classes
    ```spec
    android.add_activites = com.facebook.FacebookActivity, com.facebook.CustomTabActivity
    ```
  * Lastly, create an xml file in the same directory as `main.py`. Name it whatever you like and add this into that xml file
    ```xml
    <intent-filter>
             <action android:name="android.intent.action.VIEW" />
             <category android:name="android.intent.category.DEFAULT" />
             <category android:name="android.intent.category.BROWSABLE" />
         </intent-filter>
    ```
    Now add this xml as an intent filter in the spec file
    ```spec
    android.manifest.intent_filters = <file-name>.xml
    ```

* Do as instructed in step 5 and 6

* Skip steps 7 and 8

* For next steps, we'll be implementing few java interfaces in python.
  
  * Include few required java classes:
    ```python
    #----Java Classes For Facebook Login----#
    AccessToken= autoclass('com.facebook.AccessToken')
    CallbackManagerFactory= autoclass('com.facebook.CallbackManager$Factory')
    FacebookCallback= autoclass('com.facebook.FacebookCallback')
    FacebookException= autoclass('com.facebook.FacebookException')
    FacebookSdk= autoclass('com.facebook.FacebookSdk')
    LoginManager= autoclass('com.facebook.login.LoginManager')
    GraphRequest= autoclass('com.facebook.GraphRequest')
    ImageRequest= autoclass('com.facebook.internal.ImageRequest')

    ```
  * Now, to respond to a login result, you need to register a callback with `LoginManager`. Before that, 
    we need to implement `GraphJSONObjectCallback` class which will be used when login request succeeds and within which
    we can get user information(like, name, email, etc.)
    ```python
    class PythonGraphJSONObjectCallback(PythonJavaClass):
        __javainterfaces__= ['com/facebook/GraphRequest$GraphJSONObjectCallback']
        __javacontext__= 'app'

        @java_method('(Lorg/json/JSONObject;Lcom/facebook/GraphResponse;)V')
        def onCompleted(self, me, response):
            if response.getError():
                #handle error
                
            else:
            
                if AccessToken.isCurrentAccessTokenActive():
                    access_token= AccessToken.getCurrentAccessToken().getToken()
                else:
                    access_token= ""

                uri= ImageRequest.getProfilePictureUri(
                    me.optString("id"),  #user id
                    100,                 #image height
                    100,                 #image width
                    access_token         #access token
                )
                
                # user has been logged in. Get other info
                # and do after login stuffs(like, updating UI, etc.)
    ```
  
  * Next, we need to implement `FacebookCallback` class which will be registered with `LoginManager`.
    ```python
    class PythonFacebookCallback(PythonJavaClass):
        __javainterfaces__= ['com/facebook/FacebookCallback']
        __javacontext__= 'app'

        @java_method('(Ljava/lang/Object;)V')
        def onSuccess(self, result):

            request= GraphRequest.newMeRequest(
                result.getAccessToken(),
                PythonGraphJSONObjectCallback()
            )

            params= Bundle()
            params.putString("fields", "last_name,first_name,email")
            request.setParameters(params)
            request.executeAsync()


        @java_method('()V')
        def onCancel(self):
            #Login has been cancelled
            

        @java_method('(Lcom/facebook/FacebookException;)V')
        def onError(self, error):
            #Error in logging in
            
    ```
  
  * We then need o initialize Facebook SDK inside App's `build` method:
    ```python
    FacebookSdk.sdkInitialize(context.getApplicationContext())
    ```
  * And then register the callback with `LoginManager` inside `build` method:
    ```python
    mCallbackManager = CallbackManagerFactory.create()
    mFacebookCallback = PythonFacebookCallback()
    self.mLoginMgr = LoginManager.getInstance()
    self.mLoginMgr.registerCallback(mCallbackManager, mFacebookCallback)
    ```
  * Finally, in your `onActivityResult` method, call `callbackManager.onActivityResult` to pass the login results to the `LoginManager` via `callbackManager`. For this we just need to add one more line to our `build` method:
    ```python
    result_bind(on_activity_result=mCallbackManager.onActivityResult)
    ```
    Make sure you've `result_bind` imported:
    ```python
    from android.activity import bind as result_bind
    ```
  
  * Finally, perform the actual login with required scopes upon clicking a button. Add below codes inside a function to be called upon a button's pressing/releasing event. 
  ```python
  self.mLoginMgr.logInWithReadPermissions(
                cast(autoclass('android.app.Activity'),
                context), Arrays.asList("email", "public_profile")
                )
  ```
    


================================================
FILE: docs/prerequisites.md
================================================
### For Google Login
#
* Goto https://console.cloud.google.com/
* While on cloud console, head to `APIs & Services` > `Credentials` > Click on `+ Create Credentials` and select `OAuth client ID`
* On the following screen select `Android` under `Application Type` field and follow on-screen instructions to fill all the fields and create a client ID for Android.
* Declare Google Play services as a gradle dependency in your `buildozer.spec` file:

```spec
android.gradle_dependencies = com.google.android.gms:play-services-auth:18.0.0
```

* Add `INTERNET` permission in `buildozer.spec` file
    ```spec
    android.permissions = INTERNET
    ```

#
### For Facebook Login
##
* You need to follow their [doc](https://developers.facebook.com/docs/facebook-login/android/) along-side. So open it up in a new tab.

* Follow their instruction in step 1 and create an OAuth App. You may skip step 2.

* For step 3, add Facebook-login SDK as a gradle dependency in your `buildozer.spec` file:
 ```spec
 android.gradle_dependencies = com.facebook.android:facebook-login:7.0.0
 ```
 
* For 4th step,
  * Add `INTERNET` permission in `buildozer.spec` file
    ```spec
    android.permissions = INTERNET
    ```
  * Copy your OAuth App ID and find `android.meta_data` in buildozer.spec file and make it to look like
    ```spec
    android.meta_data = com.facebook.sdk.ApplicationId=fb<App-ID-of-your-OAuth-App>
    ```
  * Next, find `android.add_activities` in buildozer.spec file and add some activity classes
    ```spec
    android.add_activites = com.facebook.FacebookActivity, com.facebook.CustomTabActivity
    ```
  * Lastly, create an xml file in the same directory as `main.py`. Name it whatever you like and paste below text into that xml file
    ```xml
    <intent-filter>
             <action android:name="android.intent.action.VIEW" />
             <category android:name="android.intent.category.DEFAULT" />
             <category android:name="android.intent.category.BROWSABLE" />
             <data android:scheme="fb<App-ID-of-your-OAuth-App>" />
    </intent-filter>
    ```
    Now add this xml as an intent filter in the spec file
    ```spec
    android.manifest.intent_filters = <file-name>.xml
    ```
#
### For Firebase Login
##
* Make sure you've created OAuth apps for [Github](https://github.com/settings/applications/new) and/or [Twitter](https://developer.twitter.com/en/apps/create) logins before proceeding further.

* Go to [firebase console](https://console.firebase.google.com) and create a project for your application.

* Once you've created a project, add your android app into the project from the Project Overview screen and follow the on-screen instructions and finally download
the `google-services.json` file.

* Declare Firebase as a gradle dependency in your `buildozer.spec` file:
 ```spec
 android.gradle_dependencies = com.google.firebase:firebase-auth:19.3.1
 ```
 
 * Add `INTERNET` permission in `buildozer.spec` file
    ```spec
    android.permissions = INTERNET
    ```

* Next, from your project's console head to the Authentication section and then switch to the Sign-in method tab and enable the sign-in methods you want for your
app.(For kivyauth you only need to enable Github and Twitter and follow on-screen instructions)

* Now you need to tweak few settings internally:
  * Build your application once, doesn't matter if it crashes
  * Then find ***build.tmpl.gradle*** inside *.buildozer/android/platform/python-for-android/pythonforandroid/bootstraps/common/build/templates* and change gradle plugin version
  from 3.1.4 to 3.5.2 and add google-services plugin as it's required by firebase and apply the plugin:
      ```java
      buildscript {
        repositories {
           //...
        }
        dependencies {
            //make sure its 3.5.2 here instead of 3.1.4 
            classpath 'com.android.tools.build:gradle:3.5.2'

            //google-services plugin, required by firebase
            classpath 'com.google.gms:google-services:4.3.3'
        }
      }

      //...

      // At the bottom
      apply plugin: 'com.google.gms.google-services'
      ```
  
  * Paste your ***google-services.json*** inside *.buildozer/android/platform/python-for-android/pythonforandroid/bootstraps/common/build/*.
* Re-build your application
  


================================================
FILE: kivyauth/__init__.py
================================================
from kivy.logger import Logger
from kivy.utils import platform

__version__ = "2.3.3"
_log_message = "KivyAuth:" + f" {__version__}" + f' (installed at "{__file__}")'

__all__ = ("login_providers", "auto_login")

Logger.info(_log_message)


================================================
FILE: kivyauth/android/__init__.py
================================================


================================================
FILE: kivyauth/android/facebook_auth.py
================================================
from android.activity import bind as result_bind
from jnius import PythonJavaClass, autoclass, cast, java_method
from kivy.logger import Logger

CallbackManagerFactory = autoclass("com.facebook.CallbackManager$Factory")
FacebookSdk = autoclass("com.facebook.FacebookSdk")
LoginManager = autoclass("com.facebook.login.LoginManager")
AccessToken = autoclass("com.facebook.AccessToken")
GraphRequest = autoclass("com.facebook.GraphRequest")
ImageRequest = autoclass("com.facebook.internal.ImageRequest")

Bundle = autoclass("android.os.Bundle")
Arrays = autoclass("java.util.Arrays")

PythonActivity = autoclass("org.kivy.android.PythonActivity")

context = PythonActivity.mActivity
mLoginMgr = None
mList = None


__all__ = ("initialize_fb", "login_facebook", "logout_facebook")


class PythonGraphJSONObjectCallback(PythonJavaClass):
    __javainterfaces__ = ["com/facebook/GraphRequest$GraphJSONObjectCallback"]
    __javacontext__ = "app"

    def __init__(self, complete_listener):
        self.complete_listener = complete_listener
        super().__init__()

    @java_method("(Lorg/json/JSONObject;Lcom/facebook/GraphResponse;)V")
    def onCompleted(self, me, response):
        if response.getError():
            # handle error
            Logger.error("KivyAuth: Unable to retrieve profile info")

        else:

            if AccessToken.isCurrentAccessTokenActive():
                access_token = AccessToken.getCurrentAccessToken().getToken()
            else:
                access_token = ""

            uri = ImageRequest.getProfilePictureUri(
                me.optString("id"), 200, 200, access_token
            )

            Logger.info(
                "KivyAuth: Profile info retrieved successfully."
                " Calling success listener."
            )

            self.complete_listener(
                me.optString("first_name") + " " + me.optString("last_name"),
                me.optString("email"),
                uri.toString() if uri else '',
            )


class PythonFacebookCallback(PythonJavaClass):
    __javainterfaces__ = ["com/facebook/FacebookCallback"]
    __javacontext__ = "app"

    def __init__(self, success_listener, cancel_listener, error_listener):
        self.success_listener = success_listener
        self.cancel_listener = cancel_listener
        self.error_listener = error_listener

    @java_method("(Ljava/lang/Object;)V")
    def onSuccess(self, result):
        Logger.info("KivyAuth: Login success. Requesting profile info.")

        request = GraphRequest.newMeRequest(
            result.getAccessToken(),
            PythonGraphJSONObjectCallback(self.success_listener),
        )

        params = Bundle()
        params.putString("fields", "last_name,first_name,email")
        request.setParameters(params)
        request.executeAsync()

    @java_method("()V")
    def onCancel(self):
        Logger.info("KivyAuth: Login Cancelled.")
        self.cancel_listener()

    @java_method("(Lcom/facebook/FacebookException;)V")
    def onError(self, error):
        Logger.error("KivyAuth: Error logging in.")
        self.error_listener()


def initialize_fb(success_listener, error_listener, *args, **kwargs):
    """
    Function to initialize facebook login.
    Must be called inside `build` method of kivy App before actual login.

    :param: `success_listener` - Function to be called on login success
    :param: `error_listener` - Function to be called on login error
    """
    FacebookSdk.sdkInitialize(context.getApplicationContext())
    mCallbackManager = CallbackManagerFactory.create()
    mFacebookCallback = PythonFacebookCallback(
        success_listener, error_listener, error_listener
    )
    result_bind(on_activity_result=mCallbackManager.onActivityResult)

    Logger.info("KivyAuth: Initialized facebook signin")
    global mList
    mList = [mCallbackManager, mFacebookCallback]


def login_facebook():
    """
    Function to login using facebook
    """
    Logger.info("KivyAuth: Initiated facebook login")
    global mLoginMgr
    mLoginMgr = LoginManager.getInstance()
    mLoginMgr.registerCallback(*mList)
    mLoginMgr.logInWithReadPermissions(
        cast(autoclass("android.app.Activity"), context),
        Arrays.asList("email", "public_profile"),
    )


def auto_facebook():
    """
    Auto login using Facebook. You may call it `on_start`.
    """
    accessToken = AccessToken.getCurrentAccessToken()
    if accessToken and not accessToken.isExpired():
        login_facebook()
        return True


def logout_facebook(after_logout):
    """
    Logout from facebook login

    :param: `after_logout` - Function to be called after logging out
    """
    mLoginMgr.logOut()
    after_logout()
    Logger.info("KivyAuth: Logged out from facebook login")


================================================
FILE: kivyauth/android/firebase_auth.py
================================================
from android.activity import bind as result_bind
from jnius import PythonJavaClass, autoclass, java_method
from kivy.logger import Logger

FirebaseAuth = autoclass("com.google.firebase.auth.FirebaseAuth")
OAuthProvider = autoclass("com.google.firebase.auth.OAuthProvider")

PythonActivity = autoclass("org.kivy.android.PythonActivity")

context = PythonActivity.mActivity

event_success_listener = None
event_error_listener = None


class OnSuccessListener(PythonJavaClass):
    __javainterfaces__ = ["com/google/android/gms/tasks/OnSuccessListener"]
    __javacontext__ = "app"

    def __init__(self, success_listener):
        self.success_listener = success_listener

    @java_method("(Ljava/lang/Object;)V")
    def onSuccess(self, result):
        # user is signed in
        Logger.info("KivyAuth: Sign in successful using firebase.")
        user = FirebaseAuth.getInstance().getCurrentUser()

        _call_success(user)


class OnFailureListener(PythonJavaClass):
    __javainterfaces__ = ["com/google/android/gms/tasks/OnFailureListener"]
    __javacontext__ = "app"

    def __init__(self, error_listener):
        self.error_listener = error_listener

    @java_method("(Ljava/lang/Exception;)V")
    def onFailure(self, e):
        # handle exception
        Logger.info("KivyAuth: Sign in using firebase failed")
        self.error_listener()


def _call_success(user):
    event_success_listener(
        user.getDisplayName(),
        user.getEmail(),
        user.getPhotoUrl().toString() if user.getPhotoUrl() else ''
    )


def initialize_firebase(success_listener, error_listener):
    """
    Function to initialize firebase login.
    Must be called inside `build` method of kivy App before actual login.

    :param: `success_listener` - Function to be called on login success
    :param: `error_listener` - Function to be called on login error
    """
    FirebaseAuth.getInstance()
    Logger.info("KivyAuth: Initialized firebase auth")
    global event_success_listener
    event_success_listener = success_listener
    global event_error_listener
    event_error_listener = error_listener


def firebase_login(provider):
    pendingResultTask = FirebaseAuth.getPendingAuthResult()
    if pendingResultTask:
        # There's something already here! Finish the sign-in for your user.

        task = pendingResultTask.addOnSuccessListener(
            OnSuccessListener(event_success_listener)
        )
        task = task.addOnFailureListener(OnFailureListener(event_error_listener))
    else:
        # There's no pending result so you need to start the sign-in flow.

        task = FirebaseAuth.startActivityForSignInWithProvider(
            context, provider.build()
        )
        task = task.addOnSuccessListener(OnSuccessListener(event_success_listener))
        task = task.addOnFailureListener(OnFailureListener(event_error_listener))


def firebase_logout(after_logout):
    Logger.info("KivyAuth: Initiated logout using firebase")
    FirebaseAuth.getInstance().signOut()
    after_logout()
    Logger.info("KivyAuth: Logged out from firebase auth")


def auto_firebase():
    user = FirebaseAuth.getInstance().getCurrentUser()
    if user:
        _call_success(user)
        return True


def login_github():
    """
    Function to login using github
    """
    Logger.info("KivyAuth: Initiated github login")
    provider = OAuthProvider.newBuilder("github.com")
    firebase_login(provider)


def login_twitter():
    """
    Function to login using twitter
    """
    Logger.info("KivyAuth: Initiated twitter login")
    provider = OAuthProvider.newBuilder("twitter.com")
    firebase_login(provider)


def logout_twitter(after_logout):
    """
    Logout from twitter login

    :param: `after_logout` - Function to be called after logging out
    """
    firebase_logout(after_logout)


def logout_github(after_logout):
    """
    Logout from github login

    :param: `after_logout` - Function to be called after logging out
    """
    firebase_logout(after_logout)


================================================
FILE: kivyauth/android/github_auth.py
================================================
from kivy.logger import Logger
from kivyauth.android.firebase_auth import (
    firebase_login,
    firebase_logout,
    initialize_firebase,
    OAuthProvider,
    auto_firebase as auto_github,
)

__all__ = ("initialize_github", "login_github", "logout_github")


def initialize_github(succes_listener, error_listener, *args, **kwargs):
    initialize_firebase(succes_listener, error_listener)


def login_github():
    """
    Function to login using github
    """
    Logger.info("KivyAuth: Initiated github login")
    provider = OAuthProvider.newBuilder("github.com")
    firebase_login(provider)


def logout_github(after_logout):
    """
    Logout from github login

    :param: `after_logout` - Function to be called after logging out
    """
    firebase_logout(after_logout)


================================================
FILE: kivyauth/android/google_auth.py
================================================
from android.activity import bind as result_bind
from jnius import autoclass
from kivy.clock import mainthread
from kivy.logger import Logger

Gso = autoclass("com.google.android.gms.auth.api.signin.GoogleSignInOptions")
GsoBuilder = autoclass(
    "com.google.android.gms.auth.api.signin.GoogleSignInOptions$Builder"
)
GSignIn = autoclass("com.google.android.gms.auth.api.signin.GoogleSignIn")
ApiException = autoclass("com.google.android.gms.common.api.ApiException")
PythonActivity = autoclass("org.kivy.android.PythonActivity")
context = PythonActivity.mActivity

RC_SIGN_IN = 10122
mGSignInClient = None
event_success_listener = None

__all__ = ("initialize_google", "login_google", "logout_google")


class GoogleActivityListener:
    def __init__(self, success_listener, error_listener):
        self.success_listener = success_listener
        self.error_listener = error_listener

    def google_activity_listener(self, request_code, result_code, data):
        if request_code == RC_SIGN_IN:
            Logger.info("KivyAuth: google_activity_listener called.")
            task = GSignIn.getSignedInAccountFromIntent(data)
            try:
                account = task.getResult(ApiException)
                _call_success(account)

            except Exception as e:
                Logger.info("KivyAuth: Error signing in using Google. {}".format(e))
                self.error_listener()


def _call_success(account):
    if account:
        Logger.info("KivyAuth: Google Login success. Calling success listener.")
        event_success_listener(
            account.getDisplayName(),
            account.getEmail(),
            account.getPhotoUrl().toString() if account.getPhotoUrl() else '',
        )
        return True


def initialize_google(success_listener, error_listener, *args, **kwargs):
    """
    Function to initialize google login.
    Must be called inside `build` method of kivy App before actual login.

    :param: `success_listener` - Function to be called on login success
    :param: `error_listener` - Function to be called on login error
    """
    global event_success_listener
    event_success_listener = success_listener
    gso = GsoBuilder(Gso.DEFAULT_SIGN_IN).requestEmail().build()
    global mGSignInClient
    mGSignInClient = GSignIn.getClient(context, gso)
    gal = GoogleActivityListener(success_listener, error_listener)
    result_bind(on_activity_result=gal.google_activity_listener)

    Logger.info("KivyAuth: Initialized google signin")


# @mainthread
def login_google():
    """
    Function to login using google
    """
    Logger.info("KivyAuth: Initiated google login")
    signInIntent = mGSignInClient.getSignInIntent()
    context.startActivityForResult(signInIntent, RC_SIGN_IN)


def auto_google():
    """
    Auto login using Google. You may call it `on_start`.
    """
    account = GSignIn.getLastSignedInAccount(context)
    return _call_success(account)


def logout_google(after_logout):
    """
    Logout from google login

    :param: `after_logout` - Function to be called after logging out
    """
    mGSignInClient.signOut()
    after_logout()
    Logger.info("KivyAuth: Logged out from google login")


================================================
FILE: kivyauth/android/twitter_auth.py
================================================
from kivy.logger import Logger
from kivyauth.android.firebase_auth import (
    firebase_login,
    firebase_logout,
    initialize_firebase,
    OAuthProvider,
    auto_firebase as auto_twitter,
)

__all__ = ("initialize_twitter", "login_twitter", "logout_twitter")


def initialize_twitter(succes_listener, error_listener, *args, **kwargs):
    initialize_firebase(succes_listener, error_listener)


def login_twitter():
    """
    Function to login using twitter
    """
    Logger.info("KivyAuth: Initiated twitter login")
    provider = OAuthProvider.newBuilder("twitter.com")
    firebase_login(provider)


def logout_twitter(after_logout):
    """
    Logout from twitter login

    :param: `after_logout` - Function to be called after logging out
    """
    firebase_logout(after_logout)


================================================
FILE: kivyauth/desktop/__init__.py
================================================


================================================
FILE: kivyauth/desktop/facebook_auth.py
================================================
import requests
from oauthlib.oauth2 import WebApplicationClient
import json
import webbrowser
import random

from kivyauth.desktop.utils import (
    request,
    redirect,
    is_connected,
    start_server,
    app,
    _close_server_pls,
    port,
    stop_login,
)
from kivy.app import App
from kivy.clock import Clock

# facebook configuration
FACEBOOK_CLIENT_ID = ""
FACEBOOK_CLIENT_SECRET = ""
fb_authorization_endpoint = "https://www.facebook.com/v15.0/dialog/oauth?"
fb_token_endpoint = "https://graph.facebook.com/v15.0/oauth/access_token?"
fb_userinfo_endpoint = "https://graph.facebook.com/v15.0/me?"

client_facebook = None

event_success_listener = None
event_error_listener = None

__all__ = ("initialize_fb", "login_facebook", "logout_facebook")


def initialize_fb(success_listener, error_listener, client_id=None, client_secret=None):
    a = App.get_running_app()
    a.bind(on_stop=lambda *args: _close_server_pls(port))

    global event_success_listener
    event_success_listener = success_listener

    global event_error_listener
    event_error_listener = error_listener

    global FACEBOOK_CLIENT_ID
    FACEBOOK_CLIENT_ID = client_id

    global FACEBOOK_CLIENT_SECRET
    FACEBOOK_CLIENT_SECRET = client_secret

    global client_facebook
    client_facebook = WebApplicationClient(FACEBOOK_CLIENT_ID)


@app.route("/loginFacebook")
def loginFacebook():

    st = "".join([random.choice("abcdefgh1234567") for _ in range(10)])
    ds = "".join([random.choice("1234567890") for _ in range(10)])

    request_uri = client_facebook.prepare_request_uri(
        fb_authorization_endpoint,
        redirect_uri=request.base_url + "/callbackFacebook",
        scope=["email"],
        state="{st=" + st + ",ds=" + ds + "}",
    )

    return redirect(request_uri)


@app.route("/loginFacebook/callbackFacebook")
def callbackFacebook():
    code = request.args.get("code")

    # prepare a request to get tokens
    token_url, headers, body = client_facebook.prepare_token_request(
        fb_token_endpoint,
        client_id=FACEBOOK_CLIENT_ID,
        client_secret=FACEBOOK_CLIENT_SECRET,
        code=code,
        redirect_url=request.base_url,
    )

    # send the request and get the response
    token_response = requests.post(token_url, headers=headers, data=body)

    # send the request and get the response
    # app_token_response = requests.get(token_url, headers=headers, data=body)

    headers = {
        "Authorization": token_response.json()["access_token"]
        + " "
        + token_response.json()["token_type"]
    }

    request_uri = client_facebook.prepare_request_uri(
        fb_userinfo_endpoint,
        fields=["id", "name", "email", "picture"],
        access_token=token_response.json()["access_token"],
    )

    # make the request and get the response
    userinfo_response = requests.get(request_uri, headers=headers, data=None).json()
    stop_login()

    # parse the information
    if userinfo_response.get("id"):
        Clock.schedule_once(lambda *args: event_success_listener(
            userinfo_response["name"],
            userinfo_response["email"],
            userinfo_response["picture"]["data"]["url"],
        ), 0)

        return "<h2>Logged in using Facebook. Return back to the Kivy application</h2>"

    event_error_listener()
    return "User Email not available or not verified"


def login_facebook():
    if is_connected():
        start_server(port)
        webbrowser.open("https://127.0.0.1:{}/loginFacebook".format(port), 1, False)
    else:
        event_error_listener()


def logout_facebook(after_logout):
    """
    Logout from facebook login

    :param: `after_logout` - Function to be called after logging out
    """
    after_logout()


================================================
FILE: kivyauth/desktop/github_auth.py
================================================
import requests
from oauthlib.oauth2 import WebApplicationClient
import json
import webbrowser
import random
import re

from kivyauth.desktop.utils import (
    request,
    redirect,
    is_connected,
    start_server,
    app,
    _close_server_pls,
    port,
    stop_login,
)
from kivy.app import App
from kivy.clock import Clock

# github configuration
GITHUB_CLIENT_ID = ""
GITHUB_CLIENT_SECRET = ""
git_authorization_endpoint = "https://github.com/login/oauth/authorize"
git_token_endpoint = "https://github.com/login/oauth/access_token"
git_userinfo_endpoint = "https://api.github.com/user"

client_github = None

event_success_listener = None
event_error_listener = None

__all__ = ("initialize_github", "login_github", "logout_github")


def initialize_github(
    success_listener, error_listener, client_id=None, client_secret=None
):
    a = App.get_running_app()
    a.bind(on_stop=lambda *args: _close_server_pls(port))

    global event_success_listener
    event_success_listener = success_listener

    global event_error_listener
    event_error_listener = error_listener

    global GITHUB_CLIENT_ID
    GITHUB_CLIENT_ID = client_id

    global GITHUB_CLIENT_SECRET
    GITHUB_CLIENT_SECRET = client_secret

    global client_github
    client_github = WebApplicationClient(GITHUB_CLIENT_ID)

@app.route("/loginGithub")
def loginGithub():
    request_uri = client_github.prepare_request_uri(
        git_authorization_endpoint,
        redirect_uri=request.base_url + "/callbackGithub",
        scope=["read:user:email"],
        state="".join([random.choice("abcdefghijklmnopqrstuvwxyz") for _ in range(20)]),
    )
    return redirect(request_uri)

@app.route("/loginGithub/callbackGithub")
def callbackGithub():
    # Get authorization code Github sent back
    code = request.args.get("code")

    # prepare a request to get tokens
    token_url, headers, body = client_github.prepare_token_request(
        git_token_endpoint,
        client_id=GITHUB_CLIENT_ID,
        client_secret=GITHUB_CLIENT_SECRET,
        code=code,
        redirect_url=request.base_url,
        state="".join([random.choice("abcdefghijklmnopqrstuvwxyz") for _ in range(20)]),
    )

    # send the request and get the response
    token_response = requests.post(token_url, headers=headers, data=body)

    # for some reason, token_response.json() is raising an error. So gotta do it manually
    token_info = re.search(
        "^access_token=(.*)&scope=.*&token_type=(.*)$", token_response.text
    )

    headers = {"Authorization": token_info.group(2) + " " + token_info.group(1)}
    body = None

    userinfo_response = requests.get(
        git_userinfo_endpoint, headers=headers, data=body
    ).json()
    stop_login()

    # parse the information
    if userinfo_response.get("id"):
        Clock.schedule_once(lambda *args: event_success_listener(
            userinfo_response["name"],
            userinfo_response["email"],
            userinfo_response["avatar_url"],
        ), 0)
        return "<h2>Logged in using Github. Return back to the Kivy application</h2>"

    event_error_listener()
    return "User Email not available or not verified"

def login_github():
    if is_connected():
        start_server(port)
        webbrowser.open("https://127.0.0.1:{}/loginGithub".format(port), 1, False)
    else:
        event_error_listener()

def logout_github(after_logout):
    """
    Logout from github login

    :param: `after_logout` - Function to be called after logging out
    """
    after_logout()


================================================
FILE: kivyauth/desktop/google_auth.py
================================================
import requests
from oauthlib.oauth2 import WebApplicationClient
import json
import webbrowser

from kivyauth.desktop.utils import (
    request,
    redirect,
    is_connected,
    start_server,
    app,
    _close_server_pls,
    port,
    stop_login,
)
from kivy.app import App
from kivy.clock import Clock

# google configurations
GOOGLE_CLIENT_ID = ""
GOOGLE_CLIENT_SECRET = ""
GOOGLE_DISCOVERY_URL = "https://accounts.google.com/.well-known/openid-configuration"

client_google = None

event_success_listener = None
event_error_listener = None

__all__ = ("initialize_google", "login_google", "logout_google")


def get_google_provider_cfg():
    return requests.get(GOOGLE_DISCOVERY_URL).json()


def initialize_google(
    success_listener, error_listener, client_id=None, client_secret=None
):
    a = App.get_running_app()
    a.bind(on_stop=lambda *args: _close_server_pls(port))

    global event_success_listener
    event_success_listener = success_listener

    global event_error_listener
    event_error_listener = error_listener

    global GOOGLE_CLIENT_ID
    GOOGLE_CLIENT_ID = client_id

    global GOOGLE_CLIENT_SECRET
    GOOGLE_CLIENT_SECRET = client_secret

    global client_google
    client_google = WebApplicationClient(GOOGLE_CLIENT_ID)

@app.route("/loginGoogle")
def loginGoogle():
    # takeout auth endpoint url from google login
    google_provider_cfg = get_google_provider_cfg()

    authorization_endpoint = google_provider_cfg["authorization_endpoint"]
    # construct the request uri
    request_uri = client_google.prepare_request_uri(
        authorization_endpoint,
        redirect_uri=request.base_url + "/callbackGoogle",
        scope=["openid", "email", "profile"],
    )

    return redirect(request_uri)

@app.route("/loginGoogle/callbackGoogle")
def callbackGoogle():
    # Get authorization code Google sent back
    code = request.args.get("code")

    # Extract the URL to hit to get tokens
    # that allows to ask things on behalf of a user
    google_provider_cfg = get_google_provider_cfg()
    token_endpoint = google_provider_cfg["token_endpoint"]

    # prepare a request to get tokens
    token_url, headers, body = client_google.prepare_token_request(
        token_endpoint,
        authorization_response=request.url,
        redirect_url=request.base_url,
        code=code,
    )

    # send the request and get the response
    token_response = requests.post(
        token_url,
        headers=headers,
        data=body,
        auth=(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET),
    )

    # parse the token response
    client_google.parse_request_body_response(json.dumps(token_response.json()))

    # Now we already have necessary tokens
    # lets ask Google for required informations
    userinfo_endpoint = google_provider_cfg["userinfo_endpoint"]
    uri, headers, body = client_google.add_token(userinfo_endpoint)

    userinfo_response = requests.get(uri, headers=headers, data=body).json()
    stop_login()

    # parse the information
    if userinfo_response.get("email_verified"):
        Clock.schedule_once(lambda *args: event_success_listener(
            userinfo_response["name"],
            userinfo_response["email"],
            userinfo_response["picture"],
        ), 0)

        return "<h2>Logged in using Google. Return back to the Kivy application</h2>"

    event_error_listener()
    return "User Email not available or not verified"

def login_google():
    if is_connected():
        start_server(port)
        webbrowser.open("https://127.0.0.1:{}/loginGoogle".format(port), 1, False)

    else:
        event_error_listener()

def logout_google(after_logout):
    """
    Logout from google login

    :param: `after_logout` - Function to be called after logging out
    """
    after_logout()


================================================
FILE: kivyauth/desktop/twitter_auth.py
================================================
__all__ = ("initialize_twitter", "login_twitter", "logout_twitter")


def initialize_twitter(
    success_listener, error_listener, client_id=None, client_secret=None
):
    raise NotImplementedError


def login_twitter():
    raise NotImplementedError


def logout_twitter():
    raise NotImplementedError

# # twitter configuration
# TWITTER_CLIENT_ID = ""
# TWITTER_CLIENT_SECRET = ""
# tw_authorization_endpoint = "https://api.twitter.com/oauth/authorize"
# tw_token_endpoint = "https://api.twitter.com/oauth/access_token"
# tw_userinfo_endpoint = "https://api.twitter.com/user"
# tw_request_token_endpoint = "https://api.twitter.com/oauth/request_token"

# @app.route("/loginTwitter")
# def loginTwitter():

#     # construct the request uri
#     # request_uri = client_twitter.prepare_request_uri(
#     #     tw_authorization_endpoint,
#     #     redirect_uri=request.base_url + "/callbackTwitter",
#     # )
#     # return redirect(request_uri)

#     resp = requests.post(
#         tw_request_token_endpoint,
#         {
#             "oauth_callback": "https%3A%2F%2F127.0.0.1%3A9004%2FloginTwitter%2FcallbackTwitter"
#         },
#     )
#     return resp.json()


# @app.route("/loginTwitter/callbackTwitter")
# def callbackTwitter():
#     code = request.args.get("code")

#     token_url, headers, body = client_twitter.prepare_token_request(
#         tw_token_endpoint,
#         client_id=TWITTER_CLIENT_ID,
#         client_secret=TWITTER_CLIENT_SECRET,
#         code=code,
#         redirect_url=request.base_url,
#     )

#     # send the request and get the response
#     token_response = requests.post(token_url, headers=headers, data=body)

#     # for some reason, token_response.json() is raising an error. So gotta do it manually
#     token_info = re.search(
#         "^access_token=(.*)&scope=.*&token_type=(.*)$", token_response.text
#     )
#     uri = tw_userinfo_endpoint
#     headers = {"Authorization": token_info.group(2) + " " + token_info.group(1)}
#     body = None

#     global userinfo_response
#     userinfo_response = requests.get(uri, headers=headers, data=body).json()

#     # parse the information
#     if userinfo_response.get("id"):
#         close_server()
#         print(get_userinfo())
#         print(get_userinfo())
#         # return update_database(
#         #     tmp["id"], tmp["email"], tmp["picture"]["data"]["url"], tmp["name"]
#         # )
#         return "Success using twitter. Return to the app"
#     return "User Email not available or not verified", 400


# if __name__ == "__main__":

#     if is_connected():
#         port = 9004
#         start_server(port)

#         webbrowser.open("https://127.0.0.1:{}/loginGoogle".format(port), 1, False)

#     else:
#         print("Could not connect. Check connection and try again")


================================================
FILE: kivyauth/desktop/utils.py
================================================
from flask import Flask, request, redirect
import requests
import os
import threading
import socket
import random

app = Flask("Local Server: KivyAuth Login")
app.secret_key = os.urandom(26)

PATH = os.path.dirname(__file__)

port = 9004
ran_num = random.randint(1111, 9999)


def _start_server(*args):
    try:
        app.run(host="127.0.0.1", port=port, ssl_context='adhoc')
    except OSError as e:
        print(e)

def start_server(port):
    thread = threading.Thread(target=_start_server)

    thread.start()


@app.route("/kill{}".format(ran_num))
def close_server(*args, **kwargs):
    func = request.environ.get("werkzeug.server.shutdown")
    if func is None:
        raise RuntimeError("Not running with the Werkzeug Server")
    func()

    return ""

def stop_login(*args):
    _close_server_pls(port)

def _close_server_pls(port, *args):
    try:
        requests.get("https://127.0.0.1:{}/kill{}".format(port, ran_num), verify=False)
    except requests.exceptions.ConnectionError:
        pass

def is_connected():
    try:
        socket.create_connection(("www.google.com", 80))
        return True
    except OSError:
        pass
    return False


================================================
FILE: kivyauth/facebook_auth.py
================================================
from kivy.utils import platform

if platform == "android":
    from kivyauth.android.facebook_auth import (
        initialize_fb,
        login_facebook,
        logout_facebook,
    )

elif platform != "ios":
    from kivyauth.desktop.facebook_auth import (
        initialize_fb,
        login_facebook,
        logout_facebook,
    )


================================================
FILE: kivyauth/github_auth.py
================================================
from kivy.utils import platform

if platform == "android":
    from kivyauth.android.github_auth import (
        initialize_github,
        login_github,
        logout_github,
    )

elif platform != "ios":
    from kivyauth.desktop.github_auth import (
        initialize_github,
        login_github,
        logout_github,
    )


================================================
FILE: kivyauth/google_auth.py
================================================
from kivy.utils import platform

if platform == "android":
    from kivyauth.android.google_auth import (
        initialize_google,
        login_google,
        logout_google,
    )

elif platform != "ios":
    from kivyauth.desktop.google_auth import (
        initialize_google,
        login_google,
        logout_google,
    )


================================================
FILE: kivyauth/twitter_auth.py
================================================
from kivy.utils import platform

if platform == "android":
    from kivyauth.android.twitter_auth import (
        initialize_twitter,
        login_twitter,
        logout_twitter,
    )

elif platform != "ios":
    from kivyauth.desktop.twitter_auth import (
        initialize_twitter,
        login_twitter,
        logout_twitter,
    )


================================================
FILE: kivyauth/utils.py
================================================
from kivy.utils import platform

if platform == "android":

    def stop_login(*args):
        pass


elif platform != "ios":
    from kivyauth.desktop.utils import stop_login


class LoginProviders:
    google = "google"
    facebook = "facebook"
    github = "github"
    twitter = "twitter"


login_providers = LoginProviders()


def auto_login(provider):
    """
    Auto login using a given provider. You may call it `on_start`.

    :param: `provider` is one of `kivyauth.login_providers`
    """
    if platform == "android":
        if provider == login_providers.google:
            from kivyauth.android.google_auth import auto_google

            return auto_google()

        if provider == login_providers.facebook:
            from kivyauth.android.facebook_auth import auto_facebook

            return auto_facebook()

        if provider == login_providers.github:
            from kivyauth.android.github_auth import auto_github

            return auto_github()

        if provider == login_providers.twitter:
            from kivyauth.android.twitter_auth import auto_twitter

            return auto_twitter()

    else:
        raise NotImplementedError("Not yet availabe for desktop")


================================================
FILE: setup.py
================================================
from setuptools import setup
import os, re

with open("README.md", "r") as fh:
    long_description = fh.read()


def is_android():
    if "ANDROID_BOOTLOGO" in os.environ:
        return True
    return False


def get_version() -> str:
    """Get __version__ from __init__.py file."""
    version_file = os.path.join(os.path.dirname(__file__), "kivyauth", "__init__.py")
    version_file_data = open(version_file, "rt", encoding="utf-8").read()
    version_regex = r"(?<=^__version__ = ['\"])[^'\"]+(?=['\"]$)"
    try:
        version = re.findall(version_regex, version_file_data, re.M)[0]
        return version
    except IndexError:
        raise ValueError(f"Unable to find version string in {version_file}.")


setup(
    name="KivyAuth",
    version=get_version(),
    packages=["kivyauth"],
    package_data={"kivyauth": ["*.py", "desktop/*", "android/*"],},
    # metadata to display on PyPI
    author="Shashi Ranjan",
    author_email="shashiranjankv@gmail.com",
    description="Integrate Google, Facebook, Github & Twitter login in kivy applications ",
    long_description=long_description,
    long_description_content_type="text/markdown",
    keywords="social-login google-login facebook-login firebase-auth kivy-application kivy python",
    url="https://github.com/shashi278/social-auth-kivy",
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: Android",
        "Operating System :: Microsoft :: Windows",
        "Operating System :: OS Independent"
    ],
    install_requires=["kivy>=2.0.0", "oauthlib", "werkzeug==2.0.3", "flask==2.0.3", "requests"]
    if not is_android()
    else [],
    python_requires=">=3.6",
)
Download .txt
gitextract_31w1vpdd/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   └── workflows/
│       └── python-publish.yml
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── demo/
│   ├── bin/
│   │   └── glogin__armeabi-v7a-0.1-armeabi-v7a-debug.apk
│   ├── intents.xml
│   └── main.py
├── docs/
│   ├── integrate-firebase-auth.md
│   ├── integrate-google-facebook-login.md
│   └── prerequisites.md
├── kivyauth/
│   ├── __init__.py
│   ├── android/
│   │   ├── __init__.py
│   │   ├── facebook_auth.py
│   │   ├── firebase_auth.py
│   │   ├── github_auth.py
│   │   ├── google_auth.py
│   │   └── twitter_auth.py
│   ├── desktop/
│   │   ├── __init__.py
│   │   ├── facebook_auth.py
│   │   ├── github_auth.py
│   │   ├── google_auth.py
│   │   ├── twitter_auth.py
│   │   └── utils.py
│   ├── facebook_auth.py
│   ├── github_auth.py
│   ├── google_auth.py
│   ├── twitter_auth.py
│   └── utils.py
└── setup.py
Download .txt
SYMBOL INDEX (92 symbols across 13 files)

FILE: demo/main.py
  function show_toast (line 43) | def show_toast(text):
  function set_statusbar_color (line 50) | def set_statusbar_color():
  class Content (line 200) | class Content(BoxLayout):
  class Content (line 203) | class Content(BoxLayout):
  class LoginScreen (line 207) | class LoginScreen(Screen):
  class RectangleRaisedIconButton (line 211) | class RectangleRaisedIconButton(
  class LoginDemo (line 217) | class LoginDemo(MDApp):
    method build (line 220) | def build(self):
    method on_start (line 261) | def on_start(self):
    method show_login_progress (line 276) | def show_login_progress(self):
    method hide_login_progress (line 280) | def hide_login_progress(self):
    method fb_login (line 284) | def fb_login(self, *args):
    method gl_login (line 289) | def gl_login(self, *args):
    method git_login (line 294) | def git_login(self, *args):
    method twitter_login (line 299) | def twitter_login(self, *args):
    method logout_ (line 304) | def logout_(self):
    method after_login (line 314) | def after_login(self, name, email, photo_uri):
    method after_logout (line 325) | def after_logout(self):
    method update_ui (line 335) | def update_ui(self, name, email, photo_uri):
    method error_listener (line 348) | def error_listener(self):
    method send_to_github (line 355) | def send_to_github(self):

FILE: kivyauth/android/facebook_auth.py
  class PythonGraphJSONObjectCallback (line 25) | class PythonGraphJSONObjectCallback(PythonJavaClass):
    method __init__ (line 29) | def __init__(self, complete_listener):
    method onCompleted (line 34) | def onCompleted(self, me, response):
  class PythonFacebookCallback (line 62) | class PythonFacebookCallback(PythonJavaClass):
    method __init__ (line 66) | def __init__(self, success_listener, cancel_listener, error_listener):
    method onSuccess (line 72) | def onSuccess(self, result):
    method onCancel (line 86) | def onCancel(self):
    method onError (line 91) | def onError(self, error):
  function initialize_fb (line 96) | def initialize_fb(success_listener, error_listener, *args, **kwargs):
  function login_facebook (line 116) | def login_facebook():
  function auto_facebook (line 130) | def auto_facebook():
  function logout_facebook (line 140) | def logout_facebook(after_logout):

FILE: kivyauth/android/firebase_auth.py
  class OnSuccessListener (line 16) | class OnSuccessListener(PythonJavaClass):
    method __init__ (line 20) | def __init__(self, success_listener):
    method onSuccess (line 24) | def onSuccess(self, result):
  class OnFailureListener (line 32) | class OnFailureListener(PythonJavaClass):
    method __init__ (line 36) | def __init__(self, error_listener):
    method onFailure (line 40) | def onFailure(self, e):
  function _call_success (line 46) | def _call_success(user):
  function initialize_firebase (line 54) | def initialize_firebase(success_listener, error_listener):
  function firebase_login (line 70) | def firebase_login(provider):
  function firebase_logout (line 89) | def firebase_logout(after_logout):
  function auto_firebase (line 96) | def auto_firebase():
  function login_github (line 103) | def login_github():
  function login_twitter (line 112) | def login_twitter():
  function logout_twitter (line 121) | def logout_twitter(after_logout):
  function logout_github (line 130) | def logout_github(after_logout):

FILE: kivyauth/android/github_auth.py
  function initialize_github (line 13) | def initialize_github(succes_listener, error_listener, *args, **kwargs):
  function login_github (line 17) | def login_github():
  function logout_github (line 26) | def logout_github(after_logout):

FILE: kivyauth/android/google_auth.py
  class GoogleActivityListener (line 22) | class GoogleActivityListener:
    method __init__ (line 23) | def __init__(self, success_listener, error_listener):
    method google_activity_listener (line 27) | def google_activity_listener(self, request_code, result_code, data):
  function _call_success (line 40) | def _call_success(account):
  function initialize_google (line 51) | def initialize_google(success_listener, error_listener, *args, **kwargs):
  function login_google (line 71) | def login_google():
  function auto_google (line 80) | def auto_google():
  function logout_google (line 88) | def logout_google(after_logout):

FILE: kivyauth/android/twitter_auth.py
  function initialize_twitter (line 13) | def initialize_twitter(succes_listener, error_listener, *args, **kwargs):
  function login_twitter (line 17) | def login_twitter():
  function logout_twitter (line 26) | def logout_twitter(after_logout):

FILE: kivyauth/desktop/facebook_auth.py
  function initialize_fb (line 35) | def initialize_fb(success_listener, error_listener, client_id=None, clie...
  function loginFacebook (line 56) | def loginFacebook():
  function callbackFacebook (line 72) | def callbackFacebook():
  function login_facebook (line 120) | def login_facebook():
  function logout_facebook (line 128) | def logout_facebook(after_logout):

FILE: kivyauth/desktop/github_auth.py
  function initialize_github (line 36) | def initialize_github(
  function loginGithub (line 58) | def loginGithub():
  function callbackGithub (line 68) | def callbackGithub():
  function login_github (line 110) | def login_github():
  function logout_github (line 117) | def logout_github(after_logout):

FILE: kivyauth/desktop/google_auth.py
  function get_google_provider_cfg (line 32) | def get_google_provider_cfg():
  function initialize_google (line 36) | def initialize_google(
  function loginGoogle (line 58) | def loginGoogle():
  function callbackGoogle (line 73) | def callbackGoogle():
  function login_google (line 122) | def login_google():
  function logout_google (line 130) | def logout_google(after_logout):

FILE: kivyauth/desktop/twitter_auth.py
  function initialize_twitter (line 4) | def initialize_twitter(
  function login_twitter (line 10) | def login_twitter():
  function logout_twitter (line 14) | def logout_twitter():

FILE: kivyauth/desktop/utils.py
  function _start_server (line 17) | def _start_server(*args):
  function start_server (line 23) | def start_server(port):
  function close_server (line 30) | def close_server(*args, **kwargs):
  function stop_login (line 38) | def stop_login(*args):
  function _close_server_pls (line 41) | def _close_server_pls(port, *args):
  function is_connected (line 47) | def is_connected():

FILE: kivyauth/utils.py
  function stop_login (line 5) | def stop_login(*args):
  class LoginProviders (line 13) | class LoginProviders:
  function auto_login (line 23) | def auto_login(provider):

FILE: setup.py
  function is_android (line 8) | def is_android():
  function get_version (line 14) | def get_version() -> str:
Condensed preview — 32 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (79K chars).
[
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 727,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the b"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 595,
    "preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your fea"
  },
  {
    "path": ".github/workflows/python-publish.yml",
    "chars": 1084,
    "preview": "# This workflow will upload a Python Package using Twine when a release is created\n# For more information see: https://d"
  },
  {
    "path": ".gitignore",
    "chars": 1818,
    "preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
  },
  {
    "path": ".travis.yml",
    "chars": 1113,
    "preview": "cache: pip\nmatrix:\n  fast_finish: true\n  include:\n  - name: Black\n    env: RUN=black\n    language: python\n    python: 3."
  },
  {
    "path": "LICENSE",
    "chars": 1070,
    "preview": "MIT License\n\nCopyright (c) 2020 Shashi Ranjan\n\nPermission is hereby granted, free of charge, to any person obtaining a c"
  },
  {
    "path": "README.md",
    "chars": 5427,
    "preview": "<p align=\"center\"> <img src=\"https://raw.githubusercontent.com/shashi278/social-auth-kivy/master/demo/kivyauth_logo.png\""
  },
  {
    "path": "demo/intents.xml",
    "chars": 307,
    "preview": "<intent-filter>\n            <action android:name=\"android.intent.action.VIEW\" />\n            <category android:name=\"and"
  },
  {
    "path": "demo/main.py",
    "chars": 11297,
    "preview": "import os\nfrom dotenv import load_dotenv\n\nfrom kivy.lang.builder import Builder\nfrom kivy.metrics import dp\nfrom kivy.ui"
  },
  {
    "path": "docs/integrate-firebase-auth.md",
    "chars": 4073,
    "preview": "### Integrate Github and Twitter Login in Kivy Applications\n\n#### Firebase has been used to integrate Github and Twitter"
  },
  {
    "path": "docs/integrate-google-facebook-login.md",
    "chars": 8708,
    "preview": "## Integrate Google and Facebook Login in Kivy Applications\n\n##\n### Google Login:\n\n#### Prerequisite\n * Declare Google P"
  },
  {
    "path": "docs/prerequisites.md",
    "chars": 4311,
    "preview": "### For Google Login\n#\n* Goto https://console.cloud.google.com/\n* While on cloud console, head to `APIs & Services` > `C"
  },
  {
    "path": "kivyauth/__init__.py",
    "chars": 239,
    "preview": "from kivy.logger import Logger\nfrom kivy.utils import platform\n\n__version__ = \"2.3.3\"\n_log_message = \"KivyAuth:\" + f\" {_"
  },
  {
    "path": "kivyauth/android/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kivyauth/android/facebook_auth.py",
    "chars": 4785,
    "preview": "from android.activity import bind as result_bind\nfrom jnius import PythonJavaClass, autoclass, cast, java_method\nfrom ki"
  },
  {
    "path": "kivyauth/android/firebase_auth.py",
    "chars": 4025,
    "preview": "from android.activity import bind as result_bind\nfrom jnius import PythonJavaClass, autoclass, java_method\nfrom kivy.log"
  },
  {
    "path": "kivyauth/android/github_auth.py",
    "chars": 787,
    "preview": "from kivy.logger import Logger\nfrom kivyauth.android.firebase_auth import (\n    firebase_login,\n    firebase_logout,\n   "
  },
  {
    "path": "kivyauth/android/google_auth.py",
    "chars": 3192,
    "preview": "from android.activity import bind as result_bind\nfrom jnius import autoclass\nfrom kivy.clock import mainthread\nfrom kivy"
  },
  {
    "path": "kivyauth/android/twitter_auth.py",
    "chars": 798,
    "preview": "from kivy.logger import Logger\nfrom kivyauth.android.firebase_auth import (\n    firebase_login,\n    firebase_logout,\n   "
  },
  {
    "path": "kivyauth/desktop/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kivyauth/desktop/facebook_auth.py",
    "chars": 3745,
    "preview": "import requests\nfrom oauthlib.oauth2 import WebApplicationClient\nimport json\nimport webbrowser\nimport random\n\nfrom kivya"
  },
  {
    "path": "kivyauth/desktop/github_auth.py",
    "chars": 3530,
    "preview": "import requests\nfrom oauthlib.oauth2 import WebApplicationClient\nimport json\nimport webbrowser\nimport random\nimport re\n\n"
  },
  {
    "path": "kivyauth/desktop/google_auth.py",
    "chars": 3797,
    "preview": "import requests\nfrom oauthlib.oauth2 import WebApplicationClient\nimport json\nimport webbrowser\n\nfrom kivyauth.desktop.ut"
  },
  {
    "path": "kivyauth/desktop/twitter_auth.py",
    "chars": 2811,
    "preview": "__all__ = (\"initialize_twitter\", \"login_twitter\", \"logout_twitter\")\n\n\ndef initialize_twitter(\n    success_listener, erro"
  },
  {
    "path": "kivyauth/desktop/utils.py",
    "chars": 1169,
    "preview": "from flask import Flask, request, redirect\nimport requests\nimport os\nimport threading\nimport socket\nimport random\n\napp ="
  },
  {
    "path": "kivyauth/facebook_auth.py",
    "chars": 338,
    "preview": "from kivy.utils import platform\n\nif platform == \"android\":\n    from kivyauth.android.facebook_auth import (\n        init"
  },
  {
    "path": "kivyauth/github_auth.py",
    "chars": 334,
    "preview": "from kivy.utils import platform\n\nif platform == \"android\":\n    from kivyauth.android.github_auth import (\n        initia"
  },
  {
    "path": "kivyauth/google_auth.py",
    "chars": 334,
    "preview": "from kivy.utils import platform\n\nif platform == \"android\":\n    from kivyauth.android.google_auth import (\n        initia"
  },
  {
    "path": "kivyauth/twitter_auth.py",
    "chars": 342,
    "preview": "from kivy.utils import platform\n\nif platform == \"android\":\n    from kivyauth.android.twitter_auth import (\n        initi"
  },
  {
    "path": "kivyauth/utils.py",
    "chars": 1209,
    "preview": "from kivy.utils import platform\n\nif platform == \"android\":\n\n    def stop_login(*args):\n        pass\n\n\nelif platform != \""
  },
  {
    "path": "setup.py",
    "chars": 1738,
    "preview": "from setuptools import setup\nimport os, re\n\nwith open(\"README.md\", \"r\") as fh:\n    long_description = fh.read()\n\n\ndef is"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the shashi278/social-auth-kivy GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 32 files (33.0 MB), approximately 18.0k tokens, and a symbol index with 92 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!