├── requirements.txt ├── .github └── workflows │ └── ci.yml ├── .env.example ├── setup.py ├── personal_access_token.py ├── LICENSE ├── README.md └── .gitignore /requirements.txt: -------------------------------------------------------------------------------- 1 | requests==2.31.0 2 | python-dotenv 3 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Run tests on pull request and auto merge dependabot pull requests 2 | 3 | on: pull_request 4 | 5 | permissions: write-all 6 | 7 | jobs: 8 | dependabot_merge: 9 | uses: sipgate-io/dependabot-automerge/.github/workflows/dependabot_automerge.yml@main 10 | secrets: inherit 11 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | # Your Personal-Access-Token and the ID. 2 | # Open https://app.sipgate.com and create a new token by navigating to "Benutzereinstellungen" -> "Personal-Access-Tokens". 3 | # The token should have the `account:read` scope (see https://www.sipgate.io/rest-api/authentication#personalAccessToken for more information). 4 | TOKEN_ID = 'YOUR_SIPGATE_TOKEN_ID' 5 | TOKEN = 'YOUR_SIPGATE_TOKEN' 6 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from setuptools import setup, find_packages 4 | 5 | 6 | with open('README.md') as f: 7 | readme = f.read() 8 | 9 | with open('LICENSE') as f: 10 | license = f.read() 11 | 12 | setup( 13 | name='sipgateio-personalaccesstoken-python', 14 | version='0.1.0', 15 | description='A demonstration on how to authenticate yourself against the sipgate REST API using personal access tokens', 16 | long_description=readme, 17 | author='sipgate.io Team', 18 | author_email='io-team@sipgate.de', 19 | url='https://github.com/sipgate-io/sipgateio-personalaccesstoken-python', 20 | license=license, 21 | packages=find_packages(exclude=()) 22 | ) 23 | -------------------------------------------------------------------------------- /personal_access_token.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import requests 3 | import os 4 | from os.path import join, dirname 5 | from dotenv import load_dotenv 6 | import requests 7 | 8 | load_dotenv() 9 | 10 | token = os.environ.get("TOKEN") 11 | token_id = os.environ.get("TOKEN_ID") 12 | 13 | 14 | def personal_access_token(): 15 | base_url = 'https://api.sipgate.com/v2' 16 | 17 | credentials = (token_id + ':' + token).encode('utf-8') 18 | base64_encoded_credentials = base64.b64encode(credentials).decode('utf-8') 19 | 20 | headers = { 21 | 'Authorization': 'Basic ' + base64_encoded_credentials 22 | } 23 | 24 | response = requests.get(base_url + '/account', headers=headers) 25 | 26 | print('Status:', response.status_code) 27 | print('Body:', response.content.decode("utf-8")) 28 | 29 | 30 | if __name__ == "__main__": 31 | personal_access_token() 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | sipgate logo 2 | 3 | # sipgate.io python Personal Access Token example 4 | 5 | To demonstrate how to authenticate against the sipgate REST API using HTTP Basic Auth, we query the `/account` endpoint which provides basic account information. 6 | 7 | For further information regarding the sipgate REST API please visit https://api.sipgate.com/v2/doc. 8 | 9 | For more information on how to create a token, visit https://www.sipgate.io/rest-api/authentication#personalAccessToken. 10 | 11 | ### Prerequisites 12 | 13 | - python3 14 | - pip3 15 | 16 | ### How To Use 17 | 18 | Navigate to the project's root directory. 19 | 20 | Install dependencies: 21 | 22 | ```bash 23 | $ pip3 install -r requirements.txt 24 | ``` 25 | 26 | Create the `.env` file by copying the `.env.example`. Set the values according to the comment above each variable. 27 | 28 | The token should have the `account:read` scope. For more information about personal access tokens visit https://www.sipgate.io/rest-api/authentication#personalAccessToken. 29 | 30 | Run the application: 31 | 32 | ```bash 33 | $ python3 personal_access_token.py 34 | ``` 35 | 36 | ### How It Works 37 | 38 | Request parameters like url and headers are defined as follows: 39 | 40 | ```python 41 | base_url = 'https://api.sipgate.com/v2' 42 | token_id = 'YOUR_SIPGATE_TOKEN_ID' 43 | token = 'YOUR_SIPGATE_TOKEN' 44 | 45 | credentials = (token_id + ':' + token).encode('utf-8') 46 | base64_encoded_credentials = base64.b64encode(credentials).decode('utf-8') 47 | 48 | headers = { 49 | 'Authorization': 'Basic ' + base64_encoded_credentials 50 | } 51 | ``` 52 | 53 | **Note:** Basic Auth requires the credentials to be Base64-encoded. 54 | **Note:** The base64 encoder requires byte-like-objects. We use `.encode('utf-8')` and `.decode('utf-8')` to convert strings to byte-like-objects and vice versa. 55 | 56 | > If OAuth should be used for `Authorization` instead of Basic Auth we do not suply the auth object in the request options. Instead we set the authorization header to `Bearer` followed by a space and the access token: `` Authorization: `Bearer ${accessToken}`, ``. For an example application interacting with the sipgate API using OAuth see our [sipgate.io python OAuth example](https://github.com/sipgate-io/sipgateio-oauth-python). 57 | 58 | --- 59 | 60 | We use the python package 'requests' for request generation and execution. 61 | The requested URL consists of the base url defined above and the endpoint `/account`. 62 | This example prints the status code and response body to the console. 63 | 64 | ```python 65 | response = requests.get(base_url + '/account', headers=headers) 66 | 67 | print('Status:', response.status_code) 68 | print('Body:', response.content.decode("utf-8")) 69 | ``` 70 | 71 | ### Common Issues 72 | 73 | #### HTTP Errors 74 | 75 | | reason | errorcode | 76 | | ------------------------------- | :-------: | 77 | | token_id and/or token are wrong | 401 | 78 | | credentials not Base64-encoded | 401 | 79 | | wrong REST API endpoint | 404 | 80 | | wrong request method | 405 | 81 | 82 | ### Related 83 | 84 | - [requests documentation](http://docs.python-requests.org/en/master/) 85 | - [base64 documentation](https://docs.python.org/3/library/base64.html) 86 | 87 | ### Contact Us 88 | 89 | Please let us know how we can improve this example. 90 | If you have a specific feature request or found a bug, please use **Issues** or fork this repository and send a **pull request** with your improvements. 91 | 92 | ### License 93 | 94 | This project is licensed under **The Unlicense** (see [LICENSE file](./LICENSE)). 95 | 96 | ### External Libraries 97 | 98 | This code uses the following external libraries 99 | 100 | - requests: 101 | Licensed under the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) 102 | Website: http://docs.python-requests.org/en/master/ 103 | 104 | --- 105 | 106 | [sipgate.io](https://www.sipgate.io) | [@sipgateio](https://twitter.com/sipgateio) | [API-doc](https://api.sipgate.com/v2/doc) 107 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/vim,git,macos,linux,pycharm+all,intellij+all,visualstudiocode 3 | # Edit at https://www.gitignore.io/?templates=vim,git,macos,linux,pycharm+all,intellij+all,visualstudiocode 4 | 5 | ### Git ### 6 | # Created by git for backups. To disable backups in Git: 7 | # $ git config --global mergetool.keepBackup false 8 | *.orig 9 | 10 | # Created by git when using merge tools for conflicts 11 | *.BACKUP.* 12 | *.BASE.* 13 | *.LOCAL.* 14 | *.REMOTE.* 15 | *_BACKUP_*.txt 16 | *_BASE_*.txt 17 | *_LOCAL_*.txt 18 | *_REMOTE_*.txt 19 | 20 | ### Intellij+all ### 21 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 22 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 23 | 24 | # User-specific stuff 25 | .idea/**/workspace.xml 26 | .idea/**/tasks.xml 27 | .idea/**/usage.statistics.xml 28 | .idea/**/dictionaries 29 | .idea/**/shelf 30 | 31 | # Generated files 32 | .idea/**/contentModel.xml 33 | 34 | # Sensitive or high-churn files 35 | .idea/**/dataSources/ 36 | .idea/**/dataSources.ids 37 | .idea/**/dataSources.local.xml 38 | .idea/**/sqlDataSources.xml 39 | .idea/**/dynamic.xml 40 | .idea/**/uiDesigner.xml 41 | .idea/**/dbnavigator.xml 42 | 43 | # Gradle 44 | .idea/**/gradle.xml 45 | .idea/**/libraries 46 | 47 | # Gradle and Maven with auto-import 48 | # When using Gradle or Maven with auto-import, you should exclude module files, 49 | # since they will be recreated, and may cause churn. Uncomment if using 50 | # auto-import. 51 | # .idea/modules.xml 52 | # .idea/*.iml 53 | # .idea/modules 54 | 55 | # CMake 56 | cmake-build-*/ 57 | 58 | # Mongo Explorer plugin 59 | .idea/**/mongoSettings.xml 60 | 61 | # File-based project format 62 | *.iws 63 | 64 | # IntelliJ 65 | out/ 66 | 67 | # mpeltonen/sbt-idea plugin 68 | .idea_modules/ 69 | 70 | # JIRA plugin 71 | atlassian-ide-plugin.xml 72 | 73 | # Cursive Clojure plugin 74 | .idea/replstate.xml 75 | 76 | # Crashlytics plugin (for Android Studio and IntelliJ) 77 | com_crashlytics_export_strings.xml 78 | crashlytics.properties 79 | crashlytics-build.properties 80 | fabric.properties 81 | 82 | # Editor-based Rest Client 83 | .idea/httpRequests 84 | 85 | # Android studio 3.1+ serialized cache file 86 | .idea/caches/build_file_checksums.ser 87 | 88 | ### Intellij+all Patch ### 89 | # Ignores the whole .idea folder and all .iml files 90 | # See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 91 | 92 | .idea/ 93 | 94 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 95 | 96 | *.iml 97 | modules.xml 98 | .idea/misc.xml 99 | *.ipr 100 | 101 | # Sonarlint plugin 102 | .idea/sonarlint 103 | 104 | ### Linux ### 105 | *~ 106 | 107 | # temporary files which can be created if a process still has a handle open of a deleted file 108 | .fuse_hidden* 109 | 110 | # KDE directory preferences 111 | .directory 112 | 113 | # Linux trash folder which might appear on any partition or disk 114 | .Trash-* 115 | 116 | # .nfs files are created when an open file is removed but is still being accessed 117 | .nfs* 118 | 119 | ### macOS ### 120 | # General 121 | .DS_Store 122 | .AppleDouble 123 | .LSOverride 124 | 125 | # Icon must end with two \r 126 | Icon 127 | 128 | # Thumbnails 129 | ._* 130 | 131 | # Files that might appear in the root of a volume 132 | .DocumentRevisions-V100 133 | .fseventsd 134 | .Spotlight-V100 135 | .TemporaryItems 136 | .Trashes 137 | .VolumeIcon.icns 138 | .com.apple.timemachine.donotpresent 139 | 140 | # Directories potentially created on remote AFP share 141 | .AppleDB 142 | .AppleDesktop 143 | Network Trash Folder 144 | Temporary Items 145 | .apdisk 146 | 147 | ### PyCharm+all ### 148 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 149 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 150 | 151 | # User-specific stuff 152 | 153 | # Generated files 154 | 155 | # Sensitive or high-churn files 156 | 157 | # Gradle 158 | 159 | # Gradle and Maven with auto-import 160 | # When using Gradle or Maven with auto-import, you should exclude module files, 161 | # since they will be recreated, and may cause churn. Uncomment if using 162 | # auto-import. 163 | # .idea/modules.xml 164 | # .idea/*.iml 165 | # .idea/modules 166 | 167 | # CMake 168 | 169 | # Mongo Explorer plugin 170 | 171 | # File-based project format 172 | 173 | # IntelliJ 174 | 175 | # mpeltonen/sbt-idea plugin 176 | 177 | # JIRA plugin 178 | 179 | # Cursive Clojure plugin 180 | 181 | # Crashlytics plugin (for Android Studio and IntelliJ) 182 | 183 | # Editor-based Rest Client 184 | 185 | # Android studio 3.1+ serialized cache file 186 | 187 | ### PyCharm+all Patch ### 188 | # Ignores the whole .idea folder and all .iml files 189 | # See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 190 | 191 | 192 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 193 | 194 | 195 | # Sonarlint plugin 196 | 197 | ### Vim ### 198 | # Swap 199 | [._]*.s[a-v][a-z] 200 | [._]*.sw[a-p] 201 | [._]s[a-rt-v][a-z] 202 | [._]ss[a-gi-z] 203 | [._]sw[a-p] 204 | 205 | # Session 206 | Session.vim 207 | 208 | # Temporary 209 | .netrwhist 210 | # Auto-generated tag files 211 | tags 212 | # Persistent undo 213 | [._]*.un~ 214 | 215 | ### VisualStudioCode ### 216 | .vscode/* 217 | !.vscode/settings.json 218 | !.vscode/tasks.json 219 | !.vscode/launch.json 220 | !.vscode/extensions.json 221 | 222 | ### VisualStudioCode Patch ### 223 | # Ignore all local history of files 224 | .history 225 | 226 | # End of https://www.gitignore.io/api/vim,git,macos,linux,pycharm+all,intellij+all,visualstudiocode --------------------------------------------------------------------------------