From d62bb094e97efc2903e03750ae584fb17c0990b5 Mon Sep 17 00:00:00 2001
From: Rushil Umaretiya <rushilwiz@gmail.com>
Date: Tue, 15 Dec 2020 15:15:56 -0500
Subject: [PATCH] init

---
 .github/workflows/publish-pypi.yml      |  41 +++
 LICENSE                                 | 339 ++++++++++++++++++++++++
 README.md                               |  23 ++
 build/lib/ion_oauth/__init__.py         |   0
 build/lib/ion_oauth/oauth.py            |  46 ++++
 dist/ion_oauth-0.2-py3-none-any.whl     | Bin 0 -> 9946 bytes
 dist/ion_oauth-0.2.tar.gz               | Bin 0 -> 2662 bytes
 ion_oauth.egg-info/PKG-INFO             |  39 +++
 ion_oauth.egg-info/SOURCES.txt          |  10 +
 ion_oauth.egg-info/dependency_links.txt |   1 +
 ion_oauth.egg-info/requires.txt         |   1 +
 ion_oauth.egg-info/top_level.txt        |   1 +
 ion_oauth.egg-info/zip-safe             |   1 +
 ion_oauth/__init__.py                   |   0
 ion_oauth/oauth.py                      |  46 ++++
 setup.py                                |  27 ++
 16 files changed, 575 insertions(+)
 create mode 100644 .github/workflows/publish-pypi.yml
 create mode 100644 LICENSE
 create mode 100644 README.md
 create mode 100644 build/lib/ion_oauth/__init__.py
 create mode 100644 build/lib/ion_oauth/oauth.py
 create mode 100644 dist/ion_oauth-0.2-py3-none-any.whl
 create mode 100644 dist/ion_oauth-0.2.tar.gz
 create mode 100644 ion_oauth.egg-info/PKG-INFO
 create mode 100644 ion_oauth.egg-info/SOURCES.txt
 create mode 100644 ion_oauth.egg-info/dependency_links.txt
 create mode 100644 ion_oauth.egg-info/requires.txt
 create mode 100644 ion_oauth.egg-info/top_level.txt
 create mode 100644 ion_oauth.egg-info/zip-safe
 create mode 100644 ion_oauth/__init__.py
 create mode 100644 ion_oauth/oauth.py
 create mode 100755 setup.py

diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml
new file mode 100644
index 0000000..3654c36
--- /dev/null
+++ b/.github/workflows/publish-pypi.yml
@@ -0,0 +1,41 @@
+name: Publish Python 🐍 distribution 📦 to PyPI
+
+on: push
+
+jobs:
+  deploy:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+
+      - name: Set up Python 3.8
+        uses: actions/setup-python@v2
+        with:
+          python-version: 3.8
+
+      - name: Install pypa/build
+        run: >-
+          python -m
+          pip install
+          build
+          --user
+
+      - name: Build a binary wheel and a source tarball
+        run: >-
+          python -m
+          build
+          --sdist
+          --wheel
+          --outdir dist/
+          .
+      - name: Publish distribution 📦 to Test PyPI
+        uses: pypa/gh-action-pypi-publish@master
+        with:
+          password: ${{ secrets.TEST_PYPI_API_TOKEN }}
+          repository_url: https://test.pypi.org/legacy/
+      - name: Publish distribution 📦 to PyPI
+        if: startsWith(github.ref, 'refs/tags')
+        uses: pypa/gh-action-pypi-publish@master
+        with:
+          user: __token__
+          password: ${{ secrets.PYPI_API_TOKEN }}
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..23cb790
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    {description}
+    Copyright (C) {year}  {fullname}
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  {signature of Ty Coon}, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..b857ec9
--- /dev/null
+++ b/README.md
@@ -0,0 +1,23 @@
+# ion-oauth
+Ion Oauth2 backend for [python-social-auth](https://github.com/python-social-auth/social-app-django).
+
+
+Setup
+-----
+
+Install with pip:
+
+```
+pip install ion_oauth
+```
+
+Add
+```
+AUTHENTICATION_BACKENDS = [
+    ...
+    'ion_oauth.oauth.IonOauth2',
+]
+```
+to your `settings.py` for a django project.
+
+Define `SOCIAL_AUTH_ION_KEY` and `SOCIAL_AUTH_ION_SECRET` in your settings.py by following the instructions at https://tjcsl.github.io/ion/developing/oauth.html
diff --git a/build/lib/ion_oauth/__init__.py b/build/lib/ion_oauth/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/build/lib/ion_oauth/oauth.py b/build/lib/ion_oauth/oauth.py
new file mode 100644
index 0000000..5ab4b49
--- /dev/null
+++ b/build/lib/ion_oauth/oauth.py
@@ -0,0 +1,46 @@
+# -*- coding: utf-8 -*-
+# Copyright (C) 2016 Peter Foley
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+from typing import Any, Dict, List
+from social_core.backends.oauth import BaseOAuth2
+
+class IonOauth2(BaseOAuth2):  # pylint: disable=abstract-method
+    name = "ion"
+    AUTHORIZATION_URL = "https://ion.tjhsst.edu/oauth/authorize"
+    ACCESS_TOKEN_URL = "https://ion.tjhsst.edu/oauth/token"
+    ACCESS_TOKEN_METHOD = "POST"
+    EXTRA_DATA = [("refresh_token", "refresh_token", True), ("expires_in", "expires")]
+
+    def get_scope(self) -> List[str]:
+        return ["read"]
+
+    def get_user_details(self, response: Dict[str, Any]) -> Dict[str, Any]:
+        profile = self.get_json(
+            "https://ion.tjhsst.edu/api/profile", params={"access_token": response["access_token"]}
+        )
+        # fields used to populate/update User model
+        data = {
+            key: profile[key]
+            for key in ("first_name", "last_name", "id", "is_student", "is_teacher")
+        }
+        data["username"] = profile["ion_username"]
+        data["email"] = profile["tj_email"]
+        return data
+
+    def get_user_id(self, details: Dict[str, Any], response: Any) -> int:
+        return details["id"]
\ No newline at end of file
diff --git a/dist/ion_oauth-0.2-py3-none-any.whl b/dist/ion_oauth-0.2-py3-none-any.whl
new file mode 100644
index 0000000000000000000000000000000000000000..356f78c37d021898b3e9b4c800cd9559748ea248
GIT binary patch
literal 9946
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

literal 0
HcmV?d00001

diff --git a/dist/ion_oauth-0.2.tar.gz b/dist/ion_oauth-0.2.tar.gz
new file mode 100644
index 0000000000000000000000000000000000000000..5303ab94316a9d01a09310455a727423ac95cd31
GIT binary patch
literal 2662
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
HxVZiXsmW^h

literal 0
HcmV?d00001

diff --git a/ion_oauth.egg-info/PKG-INFO b/ion_oauth.egg-info/PKG-INFO
new file mode 100644
index 0000000..606c59c
--- /dev/null
+++ b/ion_oauth.egg-info/PKG-INFO
@@ -0,0 +1,39 @@
+Metadata-Version: 2.1
+Name: ion-oauth
+Version: 0.2
+Summary: python-social-auth plugin for ion
+Home-page: https://github.com/tjcsl/ion_oauth
+Author: The TJHSST Computer Systems Lab
+Author-email: intranet@tjhsst.edu
+License: GPL
+Description: # ion-oauth
+        Ion Oauth2 backend for [python-social-auth](https://github.com/python-social-auth/social-app-django).
+        
+        
+        Setup
+        -----
+        
+        Install with pip:
+        
+        ```
+        pip install ion_oauth
+        ```
+        
+        Add
+        ```
+        AUTHENTICATION_BACKENDS = [
+            ...
+            'ion_oauth.oauth.IonOauth2',
+        ]
+        ```
+        to your `settings.py` for a django project.
+        
+        Define `SOCIAL_AUTH_ION_KEY` and `SOCIAL_AUTH_ION_SECRET` in your settings.py by following the instructions at https://tjcsl.github.io/ion/developing/oauth.html
+        
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)
+Classifier: Operating System :: POSIX :: Linux
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 3
+Description-Content-Type: text/markdown
diff --git a/ion_oauth.egg-info/SOURCES.txt b/ion_oauth.egg-info/SOURCES.txt
new file mode 100644
index 0000000..c77e43a
--- /dev/null
+++ b/ion_oauth.egg-info/SOURCES.txt
@@ -0,0 +1,10 @@
+README.md
+setup.py
+ion_oauth/__init__.py
+ion_oauth/oauth.py
+ion_oauth.egg-info/PKG-INFO
+ion_oauth.egg-info/SOURCES.txt
+ion_oauth.egg-info/dependency_links.txt
+ion_oauth.egg-info/requires.txt
+ion_oauth.egg-info/top_level.txt
+ion_oauth.egg-info/zip-safe
\ No newline at end of file
diff --git a/ion_oauth.egg-info/dependency_links.txt b/ion_oauth.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/ion_oauth.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/ion_oauth.egg-info/requires.txt b/ion_oauth.egg-info/requires.txt
new file mode 100644
index 0000000..261da20
--- /dev/null
+++ b/ion_oauth.egg-info/requires.txt
@@ -0,0 +1 @@
+python-social-auth
diff --git a/ion_oauth.egg-info/top_level.txt b/ion_oauth.egg-info/top_level.txt
new file mode 100644
index 0000000..7717c95
--- /dev/null
+++ b/ion_oauth.egg-info/top_level.txt
@@ -0,0 +1 @@
+ion_oauth
diff --git a/ion_oauth.egg-info/zip-safe b/ion_oauth.egg-info/zip-safe
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/ion_oauth.egg-info/zip-safe
@@ -0,0 +1 @@
+
diff --git a/ion_oauth/__init__.py b/ion_oauth/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/ion_oauth/oauth.py b/ion_oauth/oauth.py
new file mode 100644
index 0000000..5ab4b49
--- /dev/null
+++ b/ion_oauth/oauth.py
@@ -0,0 +1,46 @@
+# -*- coding: utf-8 -*-
+# Copyright (C) 2016 Peter Foley
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+from typing import Any, Dict, List
+from social_core.backends.oauth import BaseOAuth2
+
+class IonOauth2(BaseOAuth2):  # pylint: disable=abstract-method
+    name = "ion"
+    AUTHORIZATION_URL = "https://ion.tjhsst.edu/oauth/authorize"
+    ACCESS_TOKEN_URL = "https://ion.tjhsst.edu/oauth/token"
+    ACCESS_TOKEN_METHOD = "POST"
+    EXTRA_DATA = [("refresh_token", "refresh_token", True), ("expires_in", "expires")]
+
+    def get_scope(self) -> List[str]:
+        return ["read"]
+
+    def get_user_details(self, response: Dict[str, Any]) -> Dict[str, Any]:
+        profile = self.get_json(
+            "https://ion.tjhsst.edu/api/profile", params={"access_token": response["access_token"]}
+        )
+        # fields used to populate/update User model
+        data = {
+            key: profile[key]
+            for key in ("first_name", "last_name", "id", "is_student", "is_teacher")
+        }
+        data["username"] = profile["ion_username"]
+        data["email"] = profile["tj_email"]
+        return data
+
+    def get_user_id(self, details: Dict[str, Any], response: Any) -> int:
+        return details["id"]
\ No newline at end of file
diff --git a/setup.py b/setup.py
new file mode 100755
index 0000000..8734aba
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+from setuptools import setup, find_packages
+
+with open("README.md", "r", encoding="utf-8") as f:
+    long_description = f.read()
+
+
+setup(name="ion_oauth",
+      description="python-social-auth plugin for ion",
+      long_description=long_description,
+      long_description_content_type="text/markdown",
+      version="0.2",
+      license="GPL",
+      author="The TJHSST Computer Systems Lab",
+      author_email="intranet@tjhsst.edu",
+      url="https://github.com/tjcsl/ion_oauth",
+      zip_safe=True,
+      install_requires=['python-social-auth'],
+      packages=find_packages(),
+      classifiers=[
+          'Development Status :: 5 - Production/Stable',
+          'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)',
+          'Operating System :: POSIX :: Linux',
+          'Programming Language :: Python :: 2',
+          'Programming Language :: Python :: 3',
+      ])