-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit d242815
Showing
9 changed files
with
397 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
MIT License | ||
|
||
Copyright (c) 2022 Tristan Simpson | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
# DisGOAuth ![Stars](https://img.shields.io/github/stars/realTristan/DisGOAuth?color=brightgreen) ![Watchers](https://img.shields.io/github/watchers/realTristan/DisGOAuth?label=Watchers) | ||
![banner](https://user-images.githubusercontent.com/75189508/188035581-008c64d0-d59a-4a95-9e75-55cb3d8f4e79.png) | ||
|
||
# About | ||
- DisGOAuth is a light-weight, fast and easy-to-use module that makes using Discord's OAuth2.0 much easier. DisGOAuth uses solely native golang packages which makes it fast and secure. | ||
|
||
# Installation | ||
`go get -u github.com/realTristan/DisGOAuth` | ||
|
||
# Quick Usage | ||
```go | ||
|
||
package main | ||
|
||
// Import Packages | ||
import ( | ||
"fmt" | ||
"net/http" | ||
|
||
// Import DisGOAuth | ||
discord "github.com/realTristan/DisGOAuth" | ||
) | ||
|
||
// Main function | ||
func main() { | ||
// Establish a new discord client | ||
var dc *discord.DiscordClient = discord.Init(&discord.DiscordClient{ | ||
ClientID: "CLIENT ID", | ||
ClientSecret: "CLIENT SECRET", | ||
RedirectURI: "localhost:8000/redirect", | ||
Scopes: []string{discord.ScopeIdentify}, | ||
}) | ||
|
||
// Home Page Handler | ||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { | ||
// Send the user to the discord authentication | ||
// website. This is where they authorize access. | ||
dc.RedirectHandler(w, r, "") | ||
}) | ||
|
||
// The OAuth URL Redirect Uri | ||
http.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) { | ||
// Put this in the handler of the dc.RedirectURI | ||
// Define Variables | ||
var ( | ||
// Get the code from the redirect parameters (&code=...) | ||
codeFromURLParamaters = r.URL.Query()["code"][0] | ||
|
||
// Get the access token using the above codeFromURLParamaters | ||
accessToken string = dc.GetAccessToken(codeFromURLParamaters) | ||
|
||
// Get the authorized user's data using the above accessToken | ||
userData map[string]interface{} = discord.GetUserData(accessToken) | ||
) | ||
// Print the user data map | ||
fmt.Println(userData) | ||
}) | ||
|
||
// Listen and Serve to the incoming http requests | ||
http.ListenAndServe(":8000", nil) | ||
} | ||
``` | ||
|
||
# License | ||
MIT License | ||
|
||
Copyright (c) 2022 Tristan Simpson | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package DisGOAuth | ||
|
||
// Import Packages | ||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
) | ||
|
||
// The GetAccessTokenBody() function is used to return | ||
// the request body bytes being used in the | ||
// GetAccessToken() http request | ||
func (dc *DiscordClient) GetAccessTokenBody(code string) *bytes.Buffer { | ||
return bytes.NewBuffer([]byte(fmt.Sprintf( | ||
"client_id=%s&client_secret=%s&grant_type=authorization_code&redirect_uri=%s&code=%s&scope=identify", | ||
dc.ClientID, | ||
dc.ClientSecret, | ||
dc.RedirectURI, | ||
code, | ||
))) | ||
} | ||
|
||
// The GetAccessToken() function is used to send an api | ||
// request to discord's oauth2/token endpoint. | ||
// The function returns the token required for | ||
// accessing the authorized users data | ||
func (dc *DiscordClient) GetAccessToken(code string) string { | ||
// Establish a new request object | ||
var req, _ = http.NewRequest("POST", | ||
"https://discordapp.com/api/oauth2/token", | ||
dc.GetAccessTokenBody(code), | ||
) | ||
// Set the request object's headers | ||
req.Header = http.Header{ | ||
"Content-Type": []string{"application/x-www-form-urlencoded"}, | ||
"Accept": []string{"application/json"}, | ||
} | ||
// Send the http request using the above request object | ||
// then decode the response body and marshal it to | ||
// a readable golang map. Return the "access_token" value | ||
// from said golang map | ||
var ( | ||
// Send the http request | ||
res, _ = RequestClient.Do(req) | ||
// Readable golang map used for storing | ||
// the response body | ||
data map[string]interface{} | ||
) | ||
// Decode the response body and return | ||
// the access token | ||
json.NewDecoder(res.Body).Decode(&data) | ||
|
||
// Return the token type and the access token | ||
// combined together | ||
return data["token_type"].(string) + " " + data["access_token"].(string) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package DisGOAuth | ||
|
||
// Import Packages | ||
import ( | ||
"fmt" | ||
"net/http" | ||
) | ||
|
||
// Request Client for sending http requests | ||
var RequestClient *http.Client = &http.Client{} | ||
|
||
// The DiscordClient struct contains five primary keys | ||
/* ClientID: string { "Your Application's Client ID" } */ | ||
/* ClientSecret: string { "Your Application's Client Secret" } */ | ||
/* Scopes: []string { "Your Application's Permission Scopes (REQUIRED)" } */ | ||
/* RedirectURI: string { "The Redirect URI (This is where you use the GetUserData functions)" } */ | ||
/* OAuthURL: string { "Your Application's OAuth URL (If none is provided, one will be generated for you)" } */ | ||
type DiscordClient struct { | ||
ClientID string | ||
ClientSecret string | ||
RedirectURI string | ||
Scopes []string | ||
OAuthURL string | ||
} | ||
|
||
// The AppendScopes() function is used to append | ||
// the provided scopes to the OAuth URL. This function | ||
// is called from the InitOAuthURL() function and is | ||
// only ran if the number of provided scopes is valid. | ||
func (dc *DiscordClient) AppendScopes() { | ||
// Append the initial parameter name (scope) | ||
dc.OAuthURL += "&scope=" | ||
|
||
// For each of the discord client's scopes | ||
for i := 0; i < len(dc.Scopes); i++ { | ||
// Append the scope to the OAuth URL | ||
dc.OAuthURL += dc.Scopes[i] | ||
|
||
// If there are multiple scopes and the | ||
// current index isn't the last scope | ||
if i != len(dc.Scopes) { | ||
// Append %20 (space) | ||
dc.OAuthURL += "%20" | ||
} | ||
} | ||
} | ||
|
||
// The InitOAuthURL() function is used to initialize | ||
// a discord OAuth URL. This function is called from | ||
// the Init() function and is only ran if there is | ||
// no previously provided OAuth URL. | ||
func (dc *DiscordClient) InitOAuthURL() { | ||
// Set the OAuth URL to a formatted string | ||
// that contains the client id, redirect uri, | ||
// and response type. | ||
dc.OAuthURL = fmt.Sprintf( | ||
"https://discord.com/api/oauth2/authorize?client_id=%s&redirect_uri=%s&response_type=code&prompt=consent", | ||
dc.ClientID, | ||
dc.RedirectURI, | ||
) | ||
// Append the scopes to the OAuth URL | ||
dc.AppendScopes() | ||
} | ||
|
||
// The CheckStructErrors() function is used to check for | ||
// any invalid / empty struct values that are required | ||
// for the discord oauth to work. | ||
func (dc *DiscordClient) CheckStructErrors() { | ||
// Make sure the user has provided | ||
// a valid client id | ||
if len(dc.ClientID) < 1 { | ||
panic("DisGOAuth Error: invalid ClientID in DiscordClient (ClientID: string)") | ||
} | ||
// Make sure the user has provided | ||
// a valid client secret | ||
if len(dc.ClientSecret) < 1 { | ||
panic("DisGOAuth Error: invalid ClientSecret in DiscordClient (ClientSecret: string)") | ||
} | ||
// Make sure the user has provided | ||
// a valid redirect uri | ||
if len(dc.RedirectURI) < 1 { | ||
panic("DisGOAuth Error: invalid RedirectURI in DiscordClient (RedirectURI: string)") | ||
} | ||
// Make sure the user has provided | ||
// a sufficient number of scopes | ||
if len(dc.Scopes) < 1 { | ||
panic("DisGOAuth Error: not enough scopes in DiscordClient (Scopes: []string)") | ||
} | ||
} | ||
|
||
// The Init() function is used to initalize | ||
// the required data for the discord oauth to work | ||
// It panics if required parameters are missing from | ||
// the provided DiscordClient struct | ||
func Init(dc *DiscordClient) *DiscordClient { | ||
// Check for DiscordClient struct errors | ||
dc.CheckStructErrors() | ||
|
||
// Initialize the OAuth URL | ||
if len(dc.OAuthURL) < 40 { | ||
dc.InitOAuthURL() | ||
} | ||
// Return the discord client | ||
return dc | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module github.com/realTristan/DisGOAuth | ||
|
||
go 1.17 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package DisGOAuth | ||
|
||
// Import net/http package | ||
import "net/http" | ||
|
||
// The RedirectHandler() function is used to redirect the user | ||
// to the provided DiscordClient OAuth URL. If there is a | ||
// provided state, it will add it to said OAuth URL | ||
// | ||
// If using a state, base64encode the data beforehand, else, | ||
// set the state to "" (length: 0) | ||
func (dc *DiscordClient) RedirectHandler(w http.ResponseWriter, r *http.Request, state string) { | ||
// Create a copy of the OAuth URL | ||
var _url string = dc.OAuthURL | ||
|
||
// If the user provided a state. Make sure | ||
// the state is base64 encoded. Or else | ||
// many bugs can arise. | ||
if len(state) > 0 { | ||
_url = dc.OAuthURL + "&state=" + state | ||
} | ||
// Redirect the user to the OAuth URL | ||
http.Redirect(w, r, _url, http.StatusTemporaryRedirect) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package DisGOAuth | ||
|
||
// Constant OAuth URL Scopes | ||
const ( | ||
// Non-Whitelist | ||
ScopeIdentify = "identify" | ||
ScopeBot = "bot" | ||
ScopeEmail = "email" | ||
ScopeGuilds = "guilds" | ||
ScopeGuildsJoin = "guilds.join" | ||
ScopeConnections = "connections" | ||
ScopeGroupDMJoin = "gdm.join" | ||
ScopeMessagesRead = "messages.read" | ||
ScopeWebhookIncoming = "webhook.Incoming" | ||
ScopeApplicationsBuildsRead = "applications.builds.read" | ||
ScopeApplicationsStoreUpdate = "applications.store.update" | ||
ScopeApplicationsEntitlements = "applications.entitlements" | ||
ScopeApplicationsCommands = "applications.commands" | ||
ScopeApplicationsCommandsUpdate = "applications.commands.update" | ||
|
||
// Whitelist Only | ||
ScopeRPC = "rpc" | ||
ScopeRPCAPI = "rpc.api" | ||
ScopeRPCNotificationsRead = "rpc.notifications.read" | ||
ScopeApplicationsBuildsUpload = "applications.builds.upload" | ||
ScopeRelationshipsRead = "relationships.read" | ||
ScopeActivitiesRead = "activities.read" | ||
ScopeActivitiesWrite = "activities.write" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package main | ||
|
||
// Import Packages | ||
import ( | ||
"fmt" | ||
"net/http" | ||
|
||
// Import DisGOAuth | ||
discord "github.com/realTristan/DisGOAuth" | ||
) | ||
|
||
// Main function | ||
func main() { | ||
// Establish a new discord client | ||
var dc *discord.DiscordClient = discord.Init(&discord.DiscordClient{ | ||
ClientID: "CLIENT ID", | ||
ClientSecret: "CLIENT SECRET", | ||
RedirectURI: "localhost:8000/redirect", | ||
Scopes: []string{discord.ScopeIdentify}, | ||
}) | ||
|
||
//////////////////////////////////////////////////////////////////////// | ||
// | ||
// Home Page Handler | ||
// | ||
// It is suggested to put this in it's own function, | ||
// I only did it like for the showcase. | ||
// | ||
//////////////////////////////////////////////////////////////////////// | ||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { | ||
// Send the user to the discord authentication | ||
// website. This is where they authorize access. | ||
dc.RedirectHandler(w, r, "") | ||
}) | ||
|
||
//////////////////////////////////////////////////////////////////////// | ||
// | ||
// The OAuth URL Redirect Uri | ||
// | ||
// It is suggested to put this in it's own function, | ||
// I only did it like for the showcase. | ||
// | ||
//////////////////////////////////////////////////////////////////////// | ||
http.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) { | ||
// Put this in the handler of the dc.RedirectURI | ||
// Define Variables | ||
var ( | ||
// Get the code from the redirect parameters (&code=...) | ||
codeFromURLParamaters = r.URL.Query()["code"][0] | ||
|
||
// Get the access token using the above codeFromURLParamaters | ||
accessToken string = dc.GetAccessToken(codeFromURLParamaters) | ||
|
||
// Get the authorized user's data using the above accessToken | ||
userData map[string]interface{} = discord.GetUserData(accessToken) | ||
) | ||
// Print the user data map | ||
fmt.Println(userData) | ||
}) | ||
|
||
// Listen and Serve to the incoming http requests | ||
http.ListenAndServe(":8000", nil) | ||
} |
Oops, something went wrong.