├── OAuth.md ├── README.md └── examples └── oauth ├── java └── vertx │ ├── .editorconfig │ ├── .gitignore │ ├── .mvn │ └── wrapper │ │ ├── MavenWrapperDownloader.java │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties │ ├── README.md │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ └── main │ └── java │ └── com │ └── example │ └── pr0auth │ └── MainVerticle.java ├── kotlin └── ktor │ ├── .gitignore │ ├── README.md │ ├── build.gradle.kts │ ├── gradle.properties │ ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle.kts │ └── src │ └── main │ ├── kotlin │ └── com │ │ └── example │ │ └── Application.kt │ └── resources │ └── logback.xml ├── node ├── cli │ ├── .gitignore │ ├── README.md │ └── main.js └── express │ ├── .gitignore │ ├── README.md │ └── app.js └── python └── requests-oauthlib ├── .gitignore ├── README.md └── main.py /OAuth.md: -------------------------------------------------------------------------------- 1 | # OAuth 2.0 2 | pr0gramm.com supports OAuth 2.0 using *Grant Code Authorization* to do API requests. 3 | 4 | This page uses the hypothetical application `kellerbay.com` as a placeholder. 5 | Everything that relates to Kellerbay needs to be replaced by your application. 6 | 7 | ## Table of Contents 8 | - [OAuth 2.0](#oauth-20) 9 | - [Table of Contents](#table-of-contents) 10 | - [You'll need](#youll-need) 11 | - [Scopes](#scopes) 12 | - [Example Integrations](#example-integrations) 13 | - [Node.js](#nodejs) 14 | - [`simple-oauth2`](#simple-oauth2) 15 | - [Python](#python) 16 | - [Laravel (PHP)](#laravel-php) 17 | - [Passport.js (Node)](#passportjs-node) 18 | - [Your Example](#your-example) 19 | 20 | ## You'll need 21 | | Name | Description | Where to get | Secret? | Format | Remarks | 22 | | ------------------- | --------------------------------------------------------------- | ------------------------------------------------- | ------- | ------------- | ------- | 23 | | `client_id` | ID of your client/application | [/contact](https://pr0gramm.com/contact) **see note below** | No | `^\d+$` | | 24 | | `client_secret` | Secret needed for access token creation | Comes along with `client_id` | Yes! | `^[0-9a-f]+$` | | 25 | | `access_token_uri` | `https://pr0gramm.com/api/oauth/createAccessToken` | <-- | No | URL | | 26 | | `authorization_uri` | `https://pr0gramm.com/oauth/authorize` | <-- | No | URL | | 27 | | `redirect_uri` | The URL that user will return to; `https://kellerbay.com/login` | Your choice | No | URL | | 28 | | `scopes` | The access that your application is requesting; e.g. `user.me` | Your choice, see below | No | | | 29 | 30 | 31 | You'll also need to generate a random `state` and check whether it is the same after getting the user back from pr0gramm. [This is important](https://stackoverflow.com/questions/26132066). 32 | 33 | 34 | > [!IMPORTANT] 35 | > When requesting a client ID and a client secret, include this information in your initial request: 36 | > - **Display Name** - What the user will see as Application name 37 | > - **Public Description** - What the user should see on their app list 38 | > - **URL** - A URL to the service - e.g. `https://kellerbay.com` 39 | > - **Logo URL** - A URL to a logo, which is >= 64x64px 40 | > - **Callback URL prefix** - The prefix to the allowed callback URLs. For example, `https://kellerbay.com/auth`. https is **required**. **localhost** is always allowed. 41 | > 42 | > If one of these is missing, we cannot proceed. 43 | 44 | ### Scopes 45 | There are many scopes. Every API endpoint is represented by a scope. For example `/api/a/b` has the scope `a.b`. The most important scopes are listed here: 46 | | Name | Description | Endpoint | 47 | | --------- | --------------------------------------------------------------------------------------------------------------- | -------------- | 48 | | `user.me` | Gets the user identifier (constant across renames), ban information and other public information about the user | `/api/user/me` | 49 | 50 | **You should probably use `user.me`**, since this is the only endpoint that will be accessible with the `access_token` in case the user is banned. 51 | You can check the `banInfo` field if and how long the user is banned. 52 | 53 | Cloudflare blocks all API requests that don't have a User-Agent with error 403. Make sure to specify a User-Agent header when doing requests. This also applies to the OAuth library you are using. 54 | You don't need to supply a valid browser agent, just be honest about what your application is doing. 55 | 56 | ## Example Integrations 57 | You can also find these (and more!) integration samples in [`examples/oauth`](examples/oauth). 58 | ### Node.js 59 | 60 | #### [`simple-oauth2`](https://www.npmjs.com/package/simple-oauth2) 61 | ```js 62 | const { AuthorizationCode } = require("simple-oauth2"); 63 | const config = { 64 | client: { 65 | // See above 66 | id: "", 67 | secret: "", 68 | }, 69 | auth: { 70 | tokenHost: "https://pr0gramm.com/", 71 | tokenPath: "/api/oauth/createAccessToken", 72 | authorizePath: "/oauth/authorize", 73 | } 74 | }; 75 | 76 | const client = new AuthorizationCode(config); 77 | 78 | const authorizationUri = client.authorizeURL({ 79 | redirect_uri: "https://kellerbay.com/login/callback", 80 | scope: "user.me", 81 | state: "", // you have to generate state, see note above 82 | }); 83 | 84 | // Redirect the user to `authorizationUri` 85 | // Examples of simple-oauth2 show how, for example: 86 | // https://github.com/lelylan/simple-oauth2/blob/511e7a44a8e2a2cc7f07ca435e0130d0e3a401c2/example/github.js 87 | 88 | // In your handler for redirect_uri (`https://kellerbay.com/login/callback?code=`): 89 | const tokenResponse = await client.getToken({ 90 | redirect_uri: "https://kellerbay.com/login/callback", 91 | code, // value from query params (`?code=`) 92 | }, { 93 | headers: { 94 | "User-Agent": "simple-oauth2/1.0", // Cloudflare wants a User-Agent, otherwise they will block this request with 403 95 | }, 96 | }); 97 | // ...also check the state! 98 | 99 | // your task: save the token for that user securely 100 | 101 | // Using the token to make API requests: 102 | const userInfo = await fetch("https://pr0gramm.com/api/user/name", { 103 | headers: { 104 | Authorization: `Bearer ${tokenResponse.token.access_token}` 105 | } 106 | }).then(r => r.json()); 107 | 108 | console.log(`Hallo ${userInfo.name}`); 109 | ``` 110 | 111 | ### Python 112 | [`requests-oauthlib`](https://github.com/requests/requests-oauthlib) (OAuth support for the `requests` library) 113 | ```py 114 | #!/usr/bin/env python3 115 | from requests_oauthlib import OAuth2Session 116 | # pip3 install --user requests_oauthlib 117 | 118 | client_id = r'' 119 | client_secret = r'' 120 | redirect_uri = 'https://kellerbay.com/login/callback' 121 | scope = ['user.me'] 122 | 123 | oauth = OAuth2Session( 124 | client_id, 125 | redirect_uri=redirect_uri, 126 | scope=scope, 127 | ) 128 | 129 | authorization_url, state = oauth.authorization_url(f'https://pr0gramm.com/oauth/authorize') 130 | 131 | print(f'Please go to:') 132 | print(authorization_url) 133 | 134 | authorization_response = input('Enter the full callback URL:\n') 135 | 136 | token = oauth.fetch_token( 137 | 'https://pr0gramm.com/api/oauth/createAccessToken', 138 | client_secret=client_secret, 139 | authorization_response=authorization_response, 140 | ) 141 | 142 | # your task: save the token for that user securely 143 | 144 | # Example authenticated API call 145 | response = oauth.get('https://pr0gramm.com/api/user/name').json() 146 | print(f'Hallo {response["name"]}') 147 | ``` 148 | 149 | ### Laravel (PHP) 150 | 151 | [`Pr0gramm Socialite Provider`](https://github.com/SocialiteProviders/Providers/tree/master/src/Pr0gramm) (Requires [`Laravel Socialite`](https://laravel.com/docs/9.x/socialite)) 152 | 153 | Read the official documentation on the website ([`Socialite Providers`](https://socialiteproviders.com/Pr0gramm/)) for installation instructions. 154 | 155 | ## Passport.js (Node) 156 | [passport-pr0gramm](https://github.com/holzmaster/passport-pr0gramm), an auth strategy for [Passport.js](https://www.passportjs.org/). Can be used with Express, Fastify, Restify and all other frameworks that support Passport.js. 157 | 158 | ### Your Example 159 | Are you using a different library? We're open for contributions and love to get more samples! 160 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ![pr0gramm-Icon](https://pr0gramm.com/media/pr0gramm-notext.svg) pr0gramm API Docs [![Discord](https://img.shields.io/discord/966447170930757642?color=5865F2&label=Dev-Server&logo=discord&logoColor=white)](https://discord.gg/uAAnNmHRuJ) 2 | 3 | ## API State 4 | At the current state, pr0gramm's API is considered **unstable** and is **not versioned**. 5 | However, we try to avoid large breaking changes but cannot give any guarantee that it won't happen. You can join our [Discord Server](https://discord.gg/uAAnNmHRuJ) and get notified on when are about to deploy breaking API changes. 6 | Our discord community is open for everyone who wants to develop _anything_ that has to do with pr0gramm and/or uses the API. Bots, services, User Scripts; you name it. 7 | 8 | ## [OAuth 2.0](OAuth.md) 9 | pr0gramm.com supports OAuth 2.0 using *Grant Code Authorization* to do API requests. 10 | You can use this to provide a "Log in with pr0gramm" experience for your application as well as accessing API endpoints with user credentials without needing their password. 11 | ### Links 12 | - [Examples and further docs on using OAuth with pr0gramm](OAuth.md) 13 | - [More information on OAuth](https://en.wikipedia.org/wiki/OAuth) 14 | 15 | ## OpenAPI 16 | The latest OpenAPI spec can be found here: 17 | https://pr0gramm.com/api/spec/latest 18 | -------------------------------------------------------------------------------- /examples/oauth/java/vertx/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 2 9 | trim_trailing_whitespace = true 10 | end_of_line = lf 11 | insert_final_newline = true 12 | -------------------------------------------------------------------------------- /examples/oauth/java/vertx/.gitignore: -------------------------------------------------------------------------------- 1 | ### Vert.x ### 2 | .vertx/ 3 | 4 | ### Eclipse ### 5 | 6 | .metadata 7 | bin/ 8 | tmp/ 9 | *.tmp 10 | *.bak 11 | *.swp 12 | *~.nib 13 | local.properties 14 | .settings/ 15 | .loadpath 16 | .recommenders 17 | 18 | # External tool builders 19 | .externalToolBuilders/ 20 | 21 | # Locally stored "Eclipse launch configurations" 22 | *.launch 23 | 24 | # PyDev specific (Python IDE for Eclipse) 25 | *.pydevproject 26 | 27 | # CDT-specific (C/C++ Development Tooling) 28 | .cproject 29 | 30 | # Java annotation processor (APT) 31 | .factorypath 32 | 33 | # PDT-specific (PHP Development Tools) 34 | .buildpath 35 | 36 | # sbteclipse plugin 37 | .target 38 | 39 | # Tern plugin 40 | .tern-project 41 | 42 | # TeXlipse plugin 43 | .texlipse 44 | 45 | # STS (Spring Tool Suite) 46 | .springBeans 47 | 48 | # Code Recommenders 49 | .recommenders/ 50 | 51 | # Scala IDE specific (Scala & Java development for Eclipse) 52 | .cache-main 53 | .scala_dependencies 54 | .worksheet 55 | 56 | ### Intellij+iml ### 57 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 58 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 59 | 60 | # User-specific stuff: 61 | .idea/**/workspace.xml 62 | .idea/**/tasks.xml 63 | .idea/dictionaries 64 | 65 | # Sensitive or high-churn files: 66 | .idea/**/dataSources/ 67 | .idea/**/dataSources.ids 68 | .idea/**/dataSources.xml 69 | .idea/**/dataSources.local.xml 70 | .idea/**/sqlDataSources.xml 71 | .idea/**/dynamic.xml 72 | .idea/**/uiDesigner.xml 73 | 74 | # Gradle: 75 | .idea/**/gradle.xml 76 | .idea/**/libraries 77 | 78 | # CMake 79 | cmake-buildTool-debug/ 80 | 81 | # Mongo Explorer plugin: 82 | .idea/**/mongoSettings.xml 83 | 84 | ## File-based project format: 85 | *.iws 86 | 87 | ## Plugin-specific files: 88 | 89 | # IntelliJ 90 | /out/ 91 | 92 | # mpeltonen/sbt-idea plugin 93 | .idea_modules/ 94 | 95 | # JIRA plugin 96 | atlassian-ide-plugin.xml 97 | 98 | # Cursive Clojure plugin 99 | .idea/replstate.xml 100 | 101 | # Crashlytics plugin (for Android Studio and IntelliJ) 102 | com_crashlytics_export_strings.xml 103 | crashlytics.properties 104 | crashlytics-buildTool.properties 105 | fabric.properties 106 | 107 | ### Intellij+iml Patch ### 108 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 109 | 110 | *.iml 111 | modules.xml 112 | .idea/misc.xml 113 | *.ipr 114 | 115 | ### macOS ### 116 | *.DS_Store 117 | .AppleDouble 118 | .LSOverride 119 | 120 | # Icon must end with two \r 121 | Icon 122 | 123 | # Thumbnails 124 | ._* 125 | 126 | # Files that might appear in the root of a volume 127 | .DocumentRevisions-V100 128 | .fseventsd 129 | .Spotlight-V100 130 | .TemporaryItems 131 | .Trashes 132 | .VolumeIcon.icns 133 | .com.apple.timemachine.donotpresent 134 | 135 | # Directories potentially created on remote AFP share 136 | .AppleDB 137 | .AppleDesktop 138 | Network Trash Folder 139 | Temporary Items 140 | .apdisk 141 | 142 | ### Maven ### 143 | target/ 144 | pom.xml.tag 145 | pom.xml.releaseBackup 146 | pom.xml.versionsBackup 147 | pom.xml.next 148 | release.properties 149 | dependency-reduced-pom.xml 150 | buildNumber.properties 151 | .mvn/timing.properties 152 | 153 | # Avoid ignoring Maven wrapper jar file (.jar files are usually ignored) 154 | !/.mvn/wrapper/maven-wrapper.jar 155 | 156 | ### Gradle ### 157 | .gradle 158 | /buildTool/ 159 | 160 | # Ignore Gradle GUI config 161 | gradle-app.setting 162 | 163 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 164 | !gradle-wrapper.jar 165 | 166 | # Cache of project 167 | .gradletasknamecache 168 | 169 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 170 | # gradle/wrapper/gradle-wrapper.properties 171 | 172 | ### NetBeans ### 173 | nbproject/private/ 174 | buildTool/ 175 | nbbuild/ 176 | dist/ 177 | nbdist/ 178 | .nb-gradle/ 179 | 180 | ### VisualStudioCode ### 181 | .vscode/* 182 | !.vscode/settings.json 183 | !.vscode/tasks.json 184 | !.vscode/launch.json 185 | !.vscode/extensions.json 186 | -------------------------------------------------------------------------------- /examples/oauth/java/vertx/.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2007-present the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import java.net.*; 17 | import java.io.*; 18 | import java.nio.channels.*; 19 | import java.util.Properties; 20 | 21 | public class MavenWrapperDownloader { 22 | 23 | private static final String WRAPPER_VERSION = "0.5.6"; 24 | /** 25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 26 | */ 27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" 28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; 29 | 30 | /** 31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 32 | * use instead of the default one. 33 | */ 34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 35 | ".mvn/wrapper/maven-wrapper.properties"; 36 | 37 | /** 38 | * Path where the maven-wrapper.jar will be saved to. 39 | */ 40 | private static final String MAVEN_WRAPPER_JAR_PATH = 41 | ".mvn/wrapper/maven-wrapper.jar"; 42 | 43 | /** 44 | * Name of the property which should be used to override the default download url for the wrapper. 45 | */ 46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 47 | 48 | public static void main(String args[]) { 49 | System.out.println("- Downloader started"); 50 | File baseDirectory = new File(args[0]); 51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 52 | 53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 54 | // wrapperUrl parameter. 55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 56 | String url = DEFAULT_DOWNLOAD_URL; 57 | if(mavenWrapperPropertyFile.exists()) { 58 | FileInputStream mavenWrapperPropertyFileInputStream = null; 59 | try { 60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 61 | Properties mavenWrapperProperties = new Properties(); 62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 64 | } catch (IOException e) { 65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 66 | } finally { 67 | try { 68 | if(mavenWrapperPropertyFileInputStream != null) { 69 | mavenWrapperPropertyFileInputStream.close(); 70 | } 71 | } catch (IOException e) { 72 | // Ignore ... 73 | } 74 | } 75 | } 76 | System.out.println("- Downloading from: " + url); 77 | 78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 79 | if(!outputFile.getParentFile().exists()) { 80 | if(!outputFile.getParentFile().mkdirs()) { 81 | System.out.println( 82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 83 | } 84 | } 85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 86 | try { 87 | downloadFileFromURL(url, outputFile); 88 | System.out.println("Done"); 89 | System.exit(0); 90 | } catch (Throwable e) { 91 | System.out.println("- Error downloading"); 92 | e.printStackTrace(); 93 | System.exit(1); 94 | } 95 | } 96 | 97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { 99 | String username = System.getenv("MVNW_USERNAME"); 100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); 101 | Authenticator.setDefault(new Authenticator() { 102 | @Override 103 | protected PasswordAuthentication getPasswordAuthentication() { 104 | return new PasswordAuthentication(username, password); 105 | } 106 | }); 107 | } 108 | URL website = new URL(urlString); 109 | ReadableByteChannel rbc; 110 | rbc = Channels.newChannel(website.openStream()); 111 | FileOutputStream fos = new FileOutputStream(destination); 112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 113 | fos.close(); 114 | rbc.close(); 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /examples/oauth/java/vertx/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pr0gramm-com/api-docs/065e44b39c52cebbf9f7defefe23562bf4ac163e/examples/oauth/java/vertx/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /examples/oauth/java/vertx/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip 18 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar 19 | -------------------------------------------------------------------------------- /examples/oauth/java/vertx/README.md: -------------------------------------------------------------------------------- 1 | # Simple Vert.x Example 2 | 3 | ![https://vertx.io](https://img.shields.io/badge/vert.x-4.3.2-purple.svg) 4 | 5 | To run your application: 6 | ``` 7 | ./mvnw clean compile exec:java 8 | ``` 9 | -------------------------------------------------------------------------------- /examples/oauth/java/vertx/mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /usr/local/etc/mavenrc ] ; then 40 | . /usr/local/etc/mavenrc 41 | fi 42 | 43 | if [ -f /etc/mavenrc ] ; then 44 | . /etc/mavenrc 45 | fi 46 | 47 | if [ -f "$HOME/.mavenrc" ] ; then 48 | . "$HOME/.mavenrc" 49 | fi 50 | 51 | fi 52 | 53 | # OS specific support. $var _must_ be set to either true or false. 54 | cygwin=false; 55 | darwin=false; 56 | mingw=false 57 | case "`uname`" in 58 | CYGWIN*) cygwin=true ;; 59 | MINGW*) mingw=true;; 60 | Darwin*) darwin=true 61 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 62 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 63 | if [ -z "$JAVA_HOME" ]; then 64 | if [ -x "/usr/libexec/java_home" ]; then 65 | export JAVA_HOME="`/usr/libexec/java_home`" 66 | else 67 | export JAVA_HOME="/Library/Java/Home" 68 | fi 69 | fi 70 | ;; 71 | esac 72 | 73 | if [ -z "$JAVA_HOME" ] ; then 74 | if [ -r /etc/gentoo-release ] ; then 75 | JAVA_HOME=`java-config --jre-home` 76 | fi 77 | fi 78 | 79 | if [ -z "$M2_HOME" ] ; then 80 | ## resolve links - $0 may be a link to maven's home 81 | PRG="$0" 82 | 83 | # need this for relative symlinks 84 | while [ -h "$PRG" ] ; do 85 | ls=`ls -ld "$PRG"` 86 | link=`expr "$ls" : '.*-> \(.*\)$'` 87 | if expr "$link" : '/.*' > /dev/null; then 88 | PRG="$link" 89 | else 90 | PRG="`dirname "$PRG"`/$link" 91 | fi 92 | done 93 | 94 | saveddir=`pwd` 95 | 96 | M2_HOME=`dirname "$PRG"`/.. 97 | 98 | # make it fully qualified 99 | M2_HOME=`cd "$M2_HOME" && pwd` 100 | 101 | cd "$saveddir" 102 | # echo Using m2 at $M2_HOME 103 | fi 104 | 105 | # For Cygwin, ensure paths are in UNIX format before anything is touched 106 | if $cygwin ; then 107 | [ -n "$M2_HOME" ] && 108 | M2_HOME=`cygpath --unix "$M2_HOME"` 109 | [ -n "$JAVA_HOME" ] && 110 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 111 | [ -n "$CLASSPATH" ] && 112 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 113 | fi 114 | 115 | # For Mingw, ensure paths are in UNIX format before anything is touched 116 | if $mingw ; then 117 | [ -n "$M2_HOME" ] && 118 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 119 | [ -n "$JAVA_HOME" ] && 120 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 121 | fi 122 | 123 | if [ -z "$JAVA_HOME" ]; then 124 | javaExecutable="`which javac`" 125 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 126 | # readlink(1) is not available as standard on Solaris 10. 127 | readLink=`which readlink` 128 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 129 | if $darwin ; then 130 | javaHome="`dirname \"$javaExecutable\"`" 131 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 132 | else 133 | javaExecutable="`readlink -f \"$javaExecutable\"`" 134 | fi 135 | javaHome="`dirname \"$javaExecutable\"`" 136 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 137 | JAVA_HOME="$javaHome" 138 | export JAVA_HOME 139 | fi 140 | fi 141 | fi 142 | 143 | if [ -z "$JAVACMD" ] ; then 144 | if [ -n "$JAVA_HOME" ] ; then 145 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 146 | # IBM's JDK on AIX uses strange locations for the executables 147 | JAVACMD="$JAVA_HOME/jre/sh/java" 148 | else 149 | JAVACMD="$JAVA_HOME/bin/java" 150 | fi 151 | else 152 | JAVACMD="`\\unset -f command; \\command -v java`" 153 | fi 154 | fi 155 | 156 | if [ ! -x "$JAVACMD" ] ; then 157 | echo "Error: JAVA_HOME is not defined correctly." >&2 158 | echo " We cannot execute $JAVACMD" >&2 159 | exit 1 160 | fi 161 | 162 | if [ -z "$JAVA_HOME" ] ; then 163 | echo "Warning: JAVA_HOME environment variable is not set." 164 | fi 165 | 166 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 167 | 168 | # traverses directory structure from process work directory to filesystem root 169 | # first directory with .mvn subdirectory is considered project base directory 170 | find_maven_basedir() { 171 | 172 | if [ -z "$1" ] 173 | then 174 | echo "Path not specified to find_maven_basedir" 175 | return 1 176 | fi 177 | 178 | basedir="$1" 179 | wdir="$1" 180 | while [ "$wdir" != '/' ] ; do 181 | if [ -d "$wdir"/.mvn ] ; then 182 | basedir=$wdir 183 | break 184 | fi 185 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 186 | if [ -d "${wdir}" ]; then 187 | wdir=`cd "$wdir/.."; pwd` 188 | fi 189 | # end of workaround 190 | done 191 | echo "${basedir}" 192 | } 193 | 194 | # concatenates all lines of a file 195 | concat_lines() { 196 | if [ -f "$1" ]; then 197 | echo "$(tr -s '\n' ' ' < "$1")" 198 | fi 199 | } 200 | 201 | BASE_DIR=`find_maven_basedir "$(pwd)"` 202 | if [ -z "$BASE_DIR" ]; then 203 | exit 1; 204 | fi 205 | 206 | ########################################################################################## 207 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 208 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 209 | ########################################################################################## 210 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then 211 | if [ "$MVNW_VERBOSE" = true ]; then 212 | echo "Found .mvn/wrapper/maven-wrapper.jar" 213 | fi 214 | else 215 | if [ "$MVNW_VERBOSE" = true ]; then 216 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." 217 | fi 218 | if [ -n "$MVNW_REPOURL" ]; then 219 | jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" 220 | else 221 | jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" 222 | fi 223 | while IFS="=" read key value; do 224 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;; 225 | esac 226 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" 227 | if [ "$MVNW_VERBOSE" = true ]; then 228 | echo "Downloading from: $jarUrl" 229 | fi 230 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" 231 | if $cygwin; then 232 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` 233 | fi 234 | 235 | if command -v wget > /dev/null; then 236 | if [ "$MVNW_VERBOSE" = true ]; then 237 | echo "Found wget ... using wget" 238 | fi 239 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 240 | wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" 241 | else 242 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" 243 | fi 244 | elif command -v curl > /dev/null; then 245 | if [ "$MVNW_VERBOSE" = true ]; then 246 | echo "Found curl ... using curl" 247 | fi 248 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 249 | curl -o "$wrapperJarPath" "$jarUrl" -f 250 | else 251 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f 252 | fi 253 | 254 | else 255 | if [ "$MVNW_VERBOSE" = true ]; then 256 | echo "Falling back to using Java to download" 257 | fi 258 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" 259 | # For Cygwin, switch paths to Windows format before running javac 260 | if $cygwin; then 261 | javaClass=`cygpath --path --windows "$javaClass"` 262 | fi 263 | if [ -e "$javaClass" ]; then 264 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 265 | if [ "$MVNW_VERBOSE" = true ]; then 266 | echo " - Compiling MavenWrapperDownloader.java ..." 267 | fi 268 | # Compiling the Java class 269 | ("$JAVA_HOME/bin/javac" "$javaClass") 270 | fi 271 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 272 | # Running the downloader 273 | if [ "$MVNW_VERBOSE" = true ]; then 274 | echo " - Running MavenWrapperDownloader.java ..." 275 | fi 276 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") 277 | fi 278 | fi 279 | fi 280 | fi 281 | ########################################################################################## 282 | # End of extension 283 | ########################################################################################## 284 | 285 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 286 | if [ "$MVNW_VERBOSE" = true ]; then 287 | echo $MAVEN_PROJECTBASEDIR 288 | fi 289 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 290 | 291 | # For Cygwin, switch paths to Windows format before running java 292 | if $cygwin; then 293 | [ -n "$M2_HOME" ] && 294 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 295 | [ -n "$JAVA_HOME" ] && 296 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 297 | [ -n "$CLASSPATH" ] && 298 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 299 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 300 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 301 | fi 302 | 303 | # Provide a "standardized" way to retrieve the CLI args that will 304 | # work with both Windows and non-Windows executions. 305 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" 306 | export MAVEN_CMD_LINE_ARGS 307 | 308 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 309 | 310 | exec "$JAVACMD" \ 311 | $MAVEN_OPTS \ 312 | $MAVEN_DEBUG_OPTS \ 313 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 314 | "-Dmaven.home=${M2_HOME}" \ 315 | "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 316 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 317 | -------------------------------------------------------------------------------- /examples/oauth/java/vertx/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* 50 | if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" 124 | 125 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 127 | ) 128 | 129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 131 | if exist %WRAPPER_JAR% ( 132 | if "%MVNW_VERBOSE%" == "true" ( 133 | echo Found %WRAPPER_JAR% 134 | ) 135 | ) else ( 136 | if not "%MVNW_REPOURL%" == "" ( 137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" 138 | ) 139 | if "%MVNW_VERBOSE%" == "true" ( 140 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 141 | echo Downloading from: %DOWNLOAD_URL% 142 | ) 143 | 144 | powershell -Command "&{"^ 145 | "$webclient = new-object System.Net.WebClient;"^ 146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 148 | "}"^ 149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ 150 | "}" 151 | if "%MVNW_VERBOSE%" == "true" ( 152 | echo Finished downloading %WRAPPER_JAR% 153 | ) 154 | ) 155 | @REM End of extension 156 | 157 | @REM Provide a "standardized" way to retrieve the CLI args that will 158 | @REM work with both Windows and non-Windows executions. 159 | set MAVEN_CMD_LINE_ARGS=%* 160 | 161 | %MAVEN_JAVA_EXE% ^ 162 | %JVM_CONFIG_MAVEN_PROPS% ^ 163 | %MAVEN_OPTS% ^ 164 | %MAVEN_DEBUG_OPTS% ^ 165 | -classpath %WRAPPER_JAR% ^ 166 | "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ 167 | %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 168 | if ERRORLEVEL 1 goto error 169 | goto end 170 | 171 | :error 172 | set ERROR_CODE=1 173 | 174 | :end 175 | @endlocal & set ERROR_CODE=%ERROR_CODE% 176 | 177 | if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost 178 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 179 | if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" 180 | if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" 181 | :skipRcPost 182 | 183 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 184 | if "%MAVEN_BATCH_PAUSE%"=="on" pause 185 | 186 | if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% 187 | 188 | cmd /C exit /B %ERROR_CODE% 189 | -------------------------------------------------------------------------------- /examples/oauth/java/vertx/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.example 8 | pr0auth 9 | 1.0.0-SNAPSHOT 10 | 11 | 12 | UTF-8 13 | 14 | 3.8.1 15 | 3.2.4 16 | 2.22.2 17 | 3.0.0 18 | 19 | 4.3.2 20 | 5.7.0 21 | 22 | com.example.pr0auth.MainVerticle 23 | io.vertx.core.Launcher 24 | 25 | 26 | 27 | 28 | 29 | io.vertx 30 | vertx-stack-depchain 31 | ${vertx.version} 32 | pom 33 | import 34 | 35 | 36 | 37 | 38 | 39 | 40 | io.vertx 41 | vertx-web 42 | 43 | 44 | io.vertx 45 | vertx-auth-oauth2 46 | 47 | 48 | io.vertx 49 | vertx-web-client 50 | 4.3.2 51 | 52 | 53 | 54 | io.vertx 55 | vertx-junit5 56 | test 57 | 58 | 59 | org.junit.jupiter 60 | junit-jupiter-api 61 | ${junit-jupiter.version} 62 | test 63 | 64 | 65 | org.junit.jupiter 66 | junit-jupiter-engine 67 | ${junit-jupiter.version} 68 | test 69 | 70 | 71 | 72 | 73 | 74 | 75 | maven-compiler-plugin 76 | ${maven-compiler-plugin.version} 77 | 78 | 11 79 | 80 | 81 | 82 | maven-shade-plugin 83 | ${maven-shade-plugin.version} 84 | 85 | 86 | package 87 | 88 | shade 89 | 90 | 91 | 92 | 94 | 95 | ${launcher.class} 96 | ${main.verticle} 97 | 98 | 99 | 100 | 101 | ${project.build.directory}/${project.artifactId}-${project.version}-fat.jar 102 | 103 | 104 | 105 | 106 | 107 | 108 | maven-surefire-plugin 109 | ${maven-surefire-plugin.version} 110 | 111 | 112 | org.codehaus.mojo 113 | exec-maven-plugin 114 | ${exec-maven-plugin.version} 115 | 116 | io.vertx.core.Launcher 117 | 118 | run 119 | ${main.verticle} 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /examples/oauth/java/vertx/src/main/java/com/example/pr0auth/MainVerticle.java: -------------------------------------------------------------------------------- 1 | package com.example.pr0auth; 2 | 3 | import io.vertx.core.AbstractVerticle; 4 | import io.vertx.core.Promise; 5 | import io.vertx.core.impl.logging.Logger; 6 | import io.vertx.core.impl.logging.LoggerFactory; 7 | import io.vertx.core.json.JsonObject; 8 | import io.vertx.ext.auth.oauth2.OAuth2Auth; 9 | import io.vertx.ext.auth.oauth2.OAuth2FlowType; 10 | import io.vertx.ext.auth.oauth2.OAuth2Options; 11 | import io.vertx.ext.web.Router; 12 | import io.vertx.ext.web.client.WebClient; 13 | import io.vertx.ext.web.client.WebClientOptions; 14 | 15 | public class MainVerticle extends AbstractVerticle { 16 | 17 | private final Logger LOGGER = LoggerFactory.getLogger(MainVerticle.class); 18 | 19 | @Override 20 | public void start(Promise startPromise) { 21 | var server = vertx.createHttpServer(); 22 | var router = Router.router(vertx); 23 | var client = WebClient.create(vertx, new WebClientOptions().setUserAgent("vertx-auth-oauth2")); 24 | var port = 8888; 25 | 26 | // Normally you would extract this code into a OAuth2Auth provider class. See for example: 27 | // https://github.com/vert-x3/vertx-auth/blob/master/vertx-auth-oauth2/src/main/java/io/vertx/ext/auth/oauth2/providers/GithubAuth.java 28 | var credentials = new OAuth2Options() 29 | .setFlow(OAuth2FlowType.AUTH_CODE) 30 | .setClientId("") 31 | .setClientSecret("") 32 | .setSite("https://pr0gramm.com") 33 | .setTokenPath("/api/oauth/createAccessToken") 34 | .setAuthorizationPath("/oauth/authorize") 35 | .setHeaders(new JsonObject() 36 | .put("User-Agent", "vertx-auth-oauth2")); // The User-Agent is necessary to get pass CloudFlare 37 | 38 | var oauth2 = OAuth2Auth.create(vertx, credentials); 39 | 40 | var authorization_uri = oauth2.authorizeURL(new JsonObject() 41 | .put("redirect_uri", "http://localhost:" + port + "/callback") 42 | .put("scope", "user.me") 43 | .put("state", "insert random state here")); 44 | 45 | router.route("/").handler(ctx -> { 46 | var response = ctx.response(); 47 | response.putHeader("content-type", "text/html"); 48 | response.end("Hi!
Log in with pr0gramm"); 49 | }); 50 | 51 | router.route("/auth").handler(ctx -> { 52 | var response = ctx.response(); 53 | response.putHeader("Location", authorization_uri) 54 | .setStatusCode(302) 55 | .end(); 56 | }); 57 | 58 | router.route("/callback").handler(ctx -> { 59 | var authCode = ctx.request().getParam("code"); 60 | // Note that the redirectUri parameter is not in snake_case 61 | var tokenRequest = new JsonObject() 62 | .put("code", authCode) 63 | .put("redirectUri", "http://localhost:" + port + "/callback"); 64 | var response = ctx.response(); 65 | 66 | oauth2.authenticate(tokenRequest) 67 | .onSuccess(user -> { 68 | LOGGER.info("User Principal: " + user.principal().toString()); 69 | String token = user.get("access_token"); 70 | 71 | client.getAbs("https://pr0gramm.com/api/user/me") 72 | .putHeader("Authorization", "Bearer " + token) 73 | .send() 74 | .onSuccess(res -> { 75 | var userInfo = res.bodyAsJsonObject(); 76 | LOGGER.info("User Info: " + userInfo.toString()); 77 | response.end(userInfo.toString()); 78 | }) 79 | .onFailure(err -> { 80 | LOGGER.error("Error: " + err.getMessage()); 81 | response.end("Error: " + err.getMessage()); 82 | }); 83 | }) 84 | .onFailure(err -> { 85 | LOGGER.error("Access Token Error: " + err.getMessage(), err); 86 | response.end(); 87 | }); 88 | }); 89 | 90 | server.requestHandler(router).listen(port, http -> { 91 | if (http.succeeded()) { 92 | startPromise.complete(); 93 | LOGGER.info("HTTP server started on port " + port); 94 | } else { 95 | startPromise.fail(http.cause()); 96 | } 97 | }); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /examples/oauth/kotlin/ktor/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | !**/src/main/**/build/ 5 | !**/src/test/**/build/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | bin/ 16 | !**/src/main/**/bin/ 17 | !**/src/test/**/bin/ 18 | 19 | ### IntelliJ IDEA ### 20 | .idea 21 | *.iws 22 | *.iml 23 | *.ipr 24 | out/ 25 | !**/src/main/**/out/ 26 | !**/src/test/**/out/ 27 | 28 | ### NetBeans ### 29 | /nbproject/private/ 30 | /nbbuild/ 31 | /dist/ 32 | /nbdist/ 33 | /.nb-gradle/ 34 | 35 | ### VS Code ### 36 | .vscode/ -------------------------------------------------------------------------------- /examples/oauth/kotlin/ktor/README.md: -------------------------------------------------------------------------------- 1 | # Ktor 2 | 3 | ``` 4 | ./gradlew run 5 | ``` 6 | -------------------------------------------------------------------------------- /examples/oauth/kotlin/ktor/build.gradle.kts: -------------------------------------------------------------------------------- 1 | val ktor_version: String by project 2 | val kotlin_version: String by project 3 | val logback_version: String by project 4 | 5 | plugins { 6 | application 7 | kotlin("jvm") version "1.7.10" 8 | } 9 | 10 | group = "com.example" 11 | version = "0.0.1" 12 | application { 13 | mainClass.set("com.example.ApplicationKt") 14 | 15 | val isDevelopment: Boolean = project.ext.has("development") 16 | applicationDefaultJvmArgs = listOf("-Dio.ktor.development=$isDevelopment") 17 | } 18 | 19 | repositories { 20 | mavenCentral() 21 | } 22 | 23 | dependencies { 24 | implementation("io.ktor:ktor-server-core-jvm:$ktor_version") 25 | implementation("io.ktor:ktor-server-auth-jvm:$ktor_version") 26 | implementation("io.ktor:ktor-server-locations-jvm:$ktor_version") 27 | implementation("io.ktor:ktor-client-core-jvm:$ktor_version") 28 | implementation("io.ktor:ktor-client-apache-jvm:$ktor_version") 29 | implementation("io.ktor:ktor-server-netty-jvm:$ktor_version") 30 | implementation("ch.qos.logback:logback-classic:$logback_version") 31 | testImplementation("io.ktor:ktor-server-tests-jvm:$ktor_version") 32 | testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version") 33 | } 34 | -------------------------------------------------------------------------------- /examples/oauth/kotlin/ktor/gradle.properties: -------------------------------------------------------------------------------- 1 | ktor_version=2.0.3 2 | kotlin_version=1.7.10 3 | logback_version=1.2.3 4 | kotlin.code.style=official 5 | -------------------------------------------------------------------------------- /examples/oauth/kotlin/ktor/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pr0gramm-com/api-docs/065e44b39c52cebbf9f7defefe23562bf4ac163e/examples/oauth/kotlin/ktor/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /examples/oauth/kotlin/ktor/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /examples/oauth/kotlin/ktor/gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | # 21 | # Gradle start up script for POSIX generated by Gradle. 22 | # 23 | # Important for running: 24 | # 25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 26 | # noncompliant, but you have some other compliant shell such as ksh or 27 | # bash, then to run this script, type that shell name before the whole 28 | # command line, like: 29 | # 30 | # ksh Gradle 31 | # 32 | # Busybox and similar reduced shells will NOT work, because this script 33 | # requires all of these POSIX shell features: 34 | # * functions; 35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 37 | # * compound commands having a testable exit status, especially «case»; 38 | # * various built-in commands including «command», «set», and «ulimit». 39 | # 40 | # Important for patching: 41 | # 42 | # (2) This script targets any POSIX shell, so it avoids extensions provided 43 | # by Bash, Ksh, etc; in particular arrays are avoided. 44 | # 45 | # The "traditional" practice of packing multiple parameters into a 46 | # space-separated string is a well documented source of bugs and security 47 | # problems, so this is (mostly) avoided, by progressively accumulating 48 | # options in "$@", and eventually passing that to Java. 49 | # 50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 52 | # see the in-line comments for details. 53 | # 54 | # There are tweaks for specific operating systems such as AIX, CygWin, 55 | # Darwin, MinGW, and NonStop. 56 | # 57 | # (3) This script is generated from the Groovy template 58 | # https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 59 | # within the Gradle project. 60 | # 61 | # You can find Gradle at https://github.com/gradle/gradle/. 62 | # 63 | ############################################################################## 64 | 65 | # Attempt to set APP_HOME 66 | 67 | # Resolve links: $0 may be a link 68 | app_path=$0 69 | 70 | # Need this for daisy-chained symlinks. 71 | while 72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 73 | [ -h "$app_path" ] 74 | do 75 | ls=$( ls -ld "$app_path" ) 76 | link=${ls#*' -> '} 77 | case $link in #( 78 | /*) app_path=$link ;; #( 79 | *) app_path=$APP_HOME$link ;; 80 | esac 81 | done 82 | 83 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit 84 | 85 | APP_NAME="Gradle" 86 | APP_BASE_NAME=${0##*/} 87 | 88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 90 | 91 | # Use the maximum available, or set MAX_FD != -1 to use that value. 92 | MAX_FD=maximum 93 | 94 | warn () { 95 | echo "$*" 96 | } >&2 97 | 98 | die () { 99 | echo 100 | echo "$*" 101 | echo 102 | exit 1 103 | } >&2 104 | 105 | # OS specific support (must be 'true' or 'false'). 106 | cygwin=false 107 | msys=false 108 | darwin=false 109 | nonstop=false 110 | case "$( uname )" in #( 111 | CYGWIN* ) cygwin=true ;; #( 112 | Darwin* ) darwin=true ;; #( 113 | MSYS* | MINGW* ) msys=true ;; #( 114 | NONSTOP* ) nonstop=true ;; 115 | esac 116 | 117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 118 | 119 | 120 | # Determine the Java command to use to start the JVM. 121 | if [ -n "$JAVA_HOME" ] ; then 122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 123 | # IBM's JDK on AIX uses strange locations for the executables 124 | JAVACMD=$JAVA_HOME/jre/sh/java 125 | else 126 | JAVACMD=$JAVA_HOME/bin/java 127 | fi 128 | if [ ! -x "$JAVACMD" ] ; then 129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 130 | 131 | Please set the JAVA_HOME variable in your environment to match the 132 | location of your Java installation." 133 | fi 134 | else 135 | JAVACMD=java 136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 137 | 138 | Please set the JAVA_HOME variable in your environment to match the 139 | location of your Java installation." 140 | fi 141 | 142 | # Increase the maximum file descriptors if we can. 143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 144 | case $MAX_FD in #( 145 | max*) 146 | MAX_FD=$( ulimit -H -n ) || 147 | warn "Could not query maximum file descriptor limit" 148 | esac 149 | case $MAX_FD in #( 150 | '' | soft) :;; #( 151 | *) 152 | ulimit -n "$MAX_FD" || 153 | warn "Could not set maximum file descriptor limit to $MAX_FD" 154 | esac 155 | fi 156 | 157 | # Collect all arguments for the java command, stacking in reverse order: 158 | # * args from the command line 159 | # * the main class name 160 | # * -classpath 161 | # * -D...appname settings 162 | # * --module-path (only if needed) 163 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 164 | 165 | # For Cygwin or MSYS, switch paths to Windows format before running java 166 | if "$cygwin" || "$msys" ; then 167 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 168 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 169 | 170 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 171 | 172 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 173 | for arg do 174 | if 175 | case $arg in #( 176 | -*) false ;; # don't mess with options #( 177 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 178 | [ -e "$t" ] ;; #( 179 | *) false ;; 180 | esac 181 | then 182 | arg=$( cygpath --path --ignore --mixed "$arg" ) 183 | fi 184 | # Roll the args list around exactly as many times as the number of 185 | # args, so each arg winds up back in the position where it started, but 186 | # possibly modified. 187 | # 188 | # NB: a `for` loop captures its iteration list before it begins, so 189 | # changing the positional parameters here affects neither the number of 190 | # iterations, nor the values presented in `arg`. 191 | shift # remove old arg 192 | set -- "$@" "$arg" # push replacement arg 193 | done 194 | fi 195 | 196 | # Collect all arguments for the java command; 197 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of 198 | # shell script including quotes and variable substitutions, so put them in 199 | # double quotes to make sure that they get re-expanded; and 200 | # * put everything else in single quotes, so that it's not re-expanded. 201 | 202 | set -- \ 203 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 204 | -classpath "$CLASSPATH" \ 205 | org.gradle.wrapper.GradleWrapperMain \ 206 | "$@" 207 | 208 | # Use "xargs" to parse quoted args. 209 | # 210 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 211 | # 212 | # In Bash we could simply go: 213 | # 214 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 215 | # set -- "${ARGS[@]}" "$@" 216 | # 217 | # but POSIX shell has neither arrays nor command substitution, so instead we 218 | # post-process each arg (as a line of input to sed) to backslash-escape any 219 | # character that might be a shell metacharacter, then use eval to reverse 220 | # that process (while maintaining the separation between arguments), and wrap 221 | # the whole thing up as a single "set" statement. 222 | # 223 | # This will of course break if any of these variables contains a newline or 224 | # an unmatched quote. 225 | # 226 | 227 | eval "set -- $( 228 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 229 | xargs -n1 | 230 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 231 | tr '\n' ' ' 232 | )" '"$@"' 233 | 234 | exec "$JAVACMD" "$@" 235 | -------------------------------------------------------------------------------- /examples/oauth/kotlin/ktor/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /examples/oauth/kotlin/ktor/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "ktor" -------------------------------------------------------------------------------- /examples/oauth/kotlin/ktor/src/main/kotlin/com/example/Application.kt: -------------------------------------------------------------------------------- 1 | package com.example 2 | 3 | import io.ktor.server.engine.* 4 | import io.ktor.server.netty.* 5 | import io.ktor.client.HttpClient 6 | import io.ktor.client.call.body 7 | import io.ktor.client.engine.apache.Apache 8 | import io.ktor.client.plugins.defaultRequest 9 | import io.ktor.client.request.get 10 | import io.ktor.client.request.header 11 | import io.ktor.client.request.headers 12 | import io.ktor.http.ContentType 13 | import io.ktor.http.HttpHeaders 14 | import io.ktor.http.HttpMethod 15 | import io.ktor.server.application.call 16 | import io.ktor.server.auth.* 17 | import io.ktor.server.response.respondRedirect 18 | import io.ktor.server.response.respondText 19 | import io.ktor.server.routing.get 20 | import io.ktor.server.routing.routing 21 | 22 | fun main() { 23 | embeddedServer(Netty, port = 8080, host = "0.0.0.0") { 24 | authentication { 25 | oauth("pr0auth") { 26 | urlProvider = { "http://localhost:8080/callback" } 27 | providerLookup = { 28 | OAuthServerSettings.OAuth2ServerSettings( 29 | name = "pr0auth", 30 | authorizeUrl = "https://pr0gramm.com/oauth/authorize", 31 | accessTokenUrl = "https://pr0gramm.com/api/oauth/createAccessToken", 32 | requestMethod = HttpMethod.Post, 33 | clientId = "<< client id >>", 34 | clientSecret = "<< client secret >>", 35 | defaultScopes = listOf("user.me") 36 | ) 37 | } 38 | client = HttpClient(Apache) { 39 | defaultRequest { 40 | header("User-Agent", "Ktor/1.0.0") 41 | } 42 | } 43 | } 44 | } 45 | 46 | routing { 47 | 48 | get("/") { 49 | call.respondText("Hi!
Log in with pr0gramm", ContentType.Text.Html) 50 | } 51 | 52 | authenticate("pr0auth") { 53 | get("auth") { 54 | call.respondRedirect("/callback") 55 | } 56 | 57 | get("/callback") { 58 | val principal: OAuthAccessTokenResponse.OAuth2? = call.authentication.principal() 59 | if (principal != null) { 60 | val client = HttpClient(Apache) 61 | call.respondText { 62 | client.get("https://pr0gramm.com/api/user/me") { 63 | headers { 64 | append(HttpHeaders.Authorization, "Bearer ${principal.accessToken}") 65 | } 66 | }.body() 67 | } 68 | } else { 69 | call.respondText("Not authenticated") 70 | } 71 | } 72 | } 73 | } 74 | }.start(wait = true) 75 | } 76 | -------------------------------------------------------------------------------- /examples/oauth/kotlin/ktor/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/oauth/node/cli/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /examples/oauth/node/cli/README.md: -------------------------------------------------------------------------------- 1 | # simple-oauth2-sample 2 | 3 | ```sh 4 | npm i -S simple-oauth2 5 | node main.js 6 | ``` 7 | -------------------------------------------------------------------------------- /examples/oauth/node/cli/main.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const { AuthorizationCode } = require("simple-oauth2"); 4 | const config = { 5 | client: { 6 | id: "", 7 | secret: "", 8 | }, 9 | auth: { 10 | tokenHost: "https://pr0gramm.com/", 11 | tokenPath: "/api/oauth/createAccessToken", 12 | authorizePath: "/oauth/authorize", 13 | } 14 | }; 15 | 16 | const client = new AuthorizationCode(config); 17 | 18 | const authorizationUri = client.authorizeURL({ 19 | redirect_uri: "https://kellerbay.com/login/callback", 20 | scope: "user.me", 21 | state: "", // you have to generate state 22 | }); 23 | 24 | 25 | console.log("Go to:"); 26 | console.log(authorizationUri); 27 | console.log(); 28 | 29 | // Redirect the user to `authorizationUri` 30 | // Examples of simple-oauth2 show how, for example: 31 | // https://github.com/lelylan/simple-oauth2/blob/511e7a44a8e2a2cc7f07ca435e0130d0e3a401c2/example/github.js 32 | 33 | // In your create a handler for redirect_uri (`https://kellerbay.com/login/callback?code=`): 34 | const tokenResponse = await client.getToken({ 35 | redirect_uri: "https://kellerbay.com/login/callback", 36 | code, // value from query params (`?code=`) 37 | }, { 38 | headers: { 39 | "User-Agent": "simple-oauth2/1.0", // Cloudflare wants a User-Agent, otherwise they will block this request with 403 40 | }, 41 | }); 42 | // ...also check the state! 43 | 44 | // your task: save the token for that user securely 45 | 46 | // Using the token to make API requests: 47 | const userInfo = await fetch("https://pr0gramm.com/api/user/me", { 48 | headers: { 49 | Authorization: `Bearer ${tokenResponse.token.access_token}` 50 | } 51 | }).then(r => r.json()); 52 | 53 | console.log(`Hallo ${userInfo.name}`); 54 | -------------------------------------------------------------------------------- /examples/oauth/node/express/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /examples/oauth/node/express/README.md: -------------------------------------------------------------------------------- 1 | # express-oauth-sample 2 | 3 | ```sh 4 | npm i -S simple-oauth2 express 5 | node app.js 6 | # server should be up at http://localhost:9090 7 | ``` 8 | -------------------------------------------------------------------------------- /examples/oauth/node/express/app.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const app = require("express")(); 4 | const { AuthorizationCode } = require("simple-oauth2"); 5 | 6 | const clientId = ""; 7 | const clientSecret = ""; 8 | 9 | const port = 9090; 10 | app.listen(port, (err) => { 11 | if (err) return console.error(err); 12 | console.log(`Express server listening at http://localhost:${port}`); 13 | 14 | const client = new AuthorizationCode({ 15 | client: { 16 | id: clientId, 17 | secret: clientSecret, 18 | }, 19 | auth: { 20 | tokenHost: "https://pr0gramm.com", 21 | tokenPath: "/api/oauth/createAccessToken", 22 | authorizePath: "/oauth/authorize", 23 | }, 24 | }); 25 | 26 | // Authorization uri definition 27 | const authorizationUri = client.authorizeURL({ 28 | redirect_uri: "http://localhost:3000/callback", 29 | scope: "user.me", 30 | state: "insert random state here", 31 | }); 32 | 33 | // Initial page redirecting to pr0gramm 34 | app.get("/auth", (req, res) => { 35 | console.log(authorizationUri); 36 | res.redirect(authorizationUri); 37 | }); 38 | 39 | // Callback service parsing the authorization token and asking for the access token 40 | app.get("/callback", async (req, res) => { 41 | try { 42 | const accessToken = await client.getToken({ 43 | redirect_uri: "http://localhost:3000/callback", 44 | code: req.query.code, 45 | }, { 46 | headers: { 47 | "User-Agent": "simple-oauth2/1.0", // Cloudflare wants a User-Agent, otherwise they will block this request with 403 48 | }, 49 | }); 50 | 51 | console.log("The resulting token: ", accessToken.token); 52 | 53 | const userInfo = await fetch(`https://pr0gramm.com/api/user/me`, { 54 | headers: { 55 | "Authorization": `Bearer ${accessToken.token.access_token}`, 56 | }, 57 | }).then(r => r.json()); 58 | 59 | console.log(userInfo); 60 | 61 | return res.send(`Hallo ${userInfo.name} :)`); 62 | } catch (error) { 63 | console.error("Access Token Error", error.message); 64 | return res.status(500).json("Authentication failed"); 65 | } 66 | }); 67 | 68 | app.get("/", (req, res) => { 69 | res.send("Hi!
Log in with pr0gramm"); 70 | }); 71 | }); 72 | -------------------------------------------------------------------------------- /examples/oauth/python/requests-oauthlib/.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | *.py[cod] 3 | -------------------------------------------------------------------------------- /examples/oauth/python/requests-oauthlib/README.md: -------------------------------------------------------------------------------- 1 | # requests-oauth-sample 2 | 3 | ```sh 4 | pip3 install --user requests_oauthlib 5 | ./main.py 6 | ``` 7 | -------------------------------------------------------------------------------- /examples/oauth/python/requests-oauthlib/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from requests_oauthlib import OAuth2Session 4 | 5 | client_id = r'' 6 | client_secret = r'' 7 | redirect_uri = 'https://localhost:9090/login' 8 | scope = [ 9 | 'user.me', 10 | ] 11 | 12 | oauth = OAuth2Session( 13 | client_id, 14 | redirect_uri=redirect_uri, 15 | scope=scope, 16 | ) 17 | 18 | authorization_url, state = oauth.authorization_url(f'https://pr0gramm.com/oauth/authorize') 19 | 20 | print(f'Please go to:') 21 | print(authorization_url) 22 | print() 23 | 24 | authorization_response = input('Enter the full callback URL:\n') 25 | 26 | token = oauth.fetch_token( 27 | f'https://pr0gramm.com/api/oauth/createAccessToken', 28 | client_secret=client_secret, 29 | authorization_response=authorization_response, 30 | ) 31 | 32 | # your task: save the token for that user securely 33 | 34 | response = oauth.get(f'https://pr0gramm.com/api/user/me').json() 35 | print(f'Hallo {response["name"]}!') 36 | --------------------------------------------------------------------------------