-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from echo-webkom/sample_auth
Sample auth
- Loading branch information
Showing
5 changed files
with
174 additions
and
22 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 |
---|---|---|
@@ -1,6 +1,6 @@ | ||
module github.com/echo-webkom/goat | ||
|
||
go 1.21.1 | ||
go 1.22.1 | ||
|
||
require github.com/markbates/goth v1.79.0 | ||
|
||
|
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,125 @@ | ||
package sample | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"io" | ||
"log" | ||
"net/http" | ||
|
||
"golang.org/x/oauth2" | ||
) | ||
|
||
func resJson(w http.ResponseWriter, j any) { | ||
b, err := json.Marshal(j) | ||
if err != nil { | ||
log.Println("JSON marshal error: " + err.Error()) | ||
w.WriteHeader(http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
w.Header().Add("Content-Type", "application/json") | ||
w.Write(b) | ||
} | ||
|
||
// Mount endpoints handled by provider for testing | ||
func mountExampleHandlers(s *http.ServeMux) { | ||
// Example login page, will be replaced with provider URL | ||
s.HandleFunc("GET /sample/auth", func(w http.ResponseWriter, r *http.Request) { | ||
http.ServeFile(w, r, "internal/auth/sample/sample_auth.html") | ||
}) | ||
|
||
// Used for token exchange | ||
s.HandleFunc("POST /sample/tokenUrl", func(w http.ResponseWriter, r *http.Request) { | ||
resJson(w, map[string]any{ | ||
"access_token": "abcdef", | ||
"token_type": "bearer", | ||
"expires_in": 3600, | ||
"refresh_token": "ghijklmno", | ||
"scope": "", | ||
}) | ||
}) | ||
|
||
// Used to fetch user data with generated token | ||
s.HandleFunc("GET /sample/tokenUrl", func(w http.ResponseWriter, r *http.Request) { | ||
resJson(w, map[string]any{ | ||
"username": "bob", | ||
"access_token": r.URL.Query().Get("access_token"), | ||
}) | ||
}) | ||
} | ||
|
||
// Todo: create generic newProvider function | ||
|
||
func New(s *http.ServeMux) { | ||
mountExampleHandlers(s) | ||
|
||
const ( | ||
// Load from .env | ||
CLIENT_ID = "john" | ||
CLIENT_SECRET = "1234" | ||
|
||
AUTH_URL = "http://localhost:8080/sample/auth" | ||
TOKEN_URL = "http://localhost:8080/sample/tokenUrl" | ||
) | ||
|
||
config := oauth2.Config{ | ||
RedirectURL: "http://localhost:8080/sample_callback", | ||
ClientID: CLIENT_ID, | ||
ClientSecret: CLIENT_SECRET, | ||
Scopes: []string{}, | ||
Endpoint: oauth2.Endpoint{ | ||
AuthURL: AUTH_URL, | ||
TokenURL: TOKEN_URL, | ||
}, | ||
} | ||
|
||
s.Handle("GET /sample_login", login(config)) | ||
s.Handle("POST /sample_callback", callback(config)) | ||
} | ||
|
||
// Creates new login handler. Should redirect to providers auth URL with | ||
// generated state. URL is given client id/secret, redirect uri, callback | ||
// uri and state. | ||
func login(config oauth2.Config) http.HandlerFunc { | ||
return func(w http.ResponseWriter, r *http.Request) { | ||
url := config.AuthCodeURL("randomstate") | ||
http.Redirect(w, r, url, http.StatusSeeOther) | ||
} | ||
} | ||
|
||
// Creates a new callback handler for the auth provider. Verifies state | ||
// and creates access token from code given by provider. This handler simply | ||
// responds with the user data json. | ||
func callback(config oauth2.Config) http.HandlerFunc { | ||
return func(w http.ResponseWriter, r *http.Request) { | ||
state := r.FormValue("state") | ||
if state != "randomstate" { | ||
w.WriteHeader(http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
code := r.FormValue("code") | ||
|
||
token, err := config.Exchange(context.Background(), code) | ||
if err != nil { | ||
w.WriteHeader(http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
token_url := config.Endpoint.TokenURL + "?access_token=" + token.AccessToken | ||
resp, err := http.Get(token_url) | ||
if err != nil { | ||
w.WriteHeader(http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
userData, err := io.ReadAll(resp.Body) | ||
if err != nil { | ||
w.WriteHeader(http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
w.Write(userData) | ||
} | ||
} |
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,19 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Document</title> | ||
</head> | ||
<body> | ||
<p>hello auth</p> | ||
|
||
<form action="/sample_callback" method="post"> | ||
<label for="code">Code:</label><br> | ||
<input type="text" id="code" name="code" value="1234"><br> | ||
<label for="state">State:</label><br> | ||
<input type="text" id="state" name="state" value="randomstate"><br><br> | ||
<input type="submit" value="Submit"> | ||
</form> | ||
</body> | ||
</html> |
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
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