Cleanup of callback script and service logs.
Updated readme with setup instructions
This commit is contained in:
parent
ccb516f8ee
commit
d22da69e2a
68
README.md
Normal file
68
README.md
Normal file
@ -0,0 +1,68 @@
|
||||
# SCM OAuth Provider
|
||||
|
||||
This is a lightweight Go server for handling OAuth flows with Gitea, Gitlab, Bitbucket, GitHub.
|
||||
|
||||
> Note: My primary use case is providing OAuth between Gitea and NetlifyCMS. Other SCMs are untested as of now.
|
||||
|
||||
## Setup
|
||||
|
||||
Open the repo and build the service:
|
||||
|
||||
```
|
||||
go build -o oauth-provider .
|
||||
```
|
||||
|
||||
Deploy the binary to your server.
|
||||
|
||||
> Dockerfile is coming soon
|
||||
|
||||
|
||||
## Config
|
||||
|
||||
The service needs some minimal configuration set before it can run.
|
||||
On the server or the location you are running the service, create a config file:
|
||||
|
||||
```
|
||||
mkdir ./env
|
||||
touch ./env/config
|
||||
```
|
||||
|
||||
The config file is TOML based. You can see a complete example in this repo at `./env/sample.config`
|
||||
|
||||
```
|
||||
[runtime]
|
||||
# Not used anywhere yet, for information only
|
||||
environment="development"
|
||||
|
||||
[server]
|
||||
# The hostname to serve from; Your external app will connect to the OAuth provider via this URL
|
||||
host="localhost"
|
||||
# The port to serve from; Used in conjunction with [server.host] to create a complete URL
|
||||
port="3000"
|
||||
# Used with OAuth provider sessions
|
||||
sessionSecret="super-secret"
|
||||
```
|
||||
|
||||
For each CMS, there are some required settings:
|
||||
|
||||
```
|
||||
[gitea]
|
||||
# OAuth Key and Secret generated on the SCM site
|
||||
key="<KEY>"
|
||||
secret="<SECRET>"
|
||||
# URL of the SCM instance
|
||||
baseUrl="https://gitea.company.com"
|
||||
# URI of the authorize endpoint (e.g for Gitea, this is shown when creating the OAuth application)
|
||||
authUri="login/oauth/authorize"
|
||||
# URI of the access_token endpoint (e.g for Gitea, this is shown when creating the OAuth application)
|
||||
accessTokenUri="login/oauth/access_token"
|
||||
# URI of the authorize endpoint if overridden (e.g for Gitea, this is shown when creating the OAuth application)
|
||||
userUri="api/v1/user"
|
||||
# Callback URL for the SCM, where it will redirect the user after they authorise. This needs to match what was given when creating the OAuth application.
|
||||
callbackUri="http://localhost:3000/callback/gitea"
|
||||
```
|
||||
|
||||
|
||||
### Credits
|
||||
|
||||
Inspiration taken from https://github.com/igk1972/netlify-cms-oauth-provider-go
|
106
main.go
106
main.go
@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net"
|
||||
@ -21,8 +22,18 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
serviceName = "netlify-cms-oauth-provider"
|
||||
serviceName = "oauth-provider"
|
||||
msgTemplate = `<!DOCTYPE html><html><head></head><body>{{.}}</body></html>`
|
||||
resTemplate = `
|
||||
<!DOCTYPE html><html><head></head><body>
|
||||
<script>
|
||||
function recieveMsg(e) {
|
||||
window.opener.postMessage("{{.OAuthResult}}", e.origin);
|
||||
}
|
||||
window.addEventListener("message", recieveMsg, false);
|
||||
window.opener.postMessage("{{.Provider}}", "*");
|
||||
</script>
|
||||
</body></html>`
|
||||
|
||||
log *logrus.Entry
|
||||
config *viper.Viper
|
||||
@ -45,7 +56,7 @@ func initProviders() {
|
||||
)
|
||||
|
||||
type settings struct {
|
||||
key, secret, baseURL, callbackURL, authURI, accessTokenURI, userURI string
|
||||
key, secret, BaseURL, CallbackURL, AuthURI, AccessTokenURI, UserURI string
|
||||
}
|
||||
|
||||
log.Info("initialising providers")
|
||||
@ -55,11 +66,11 @@ func initProviders() {
|
||||
return settings{
|
||||
key: config.GetString(name + ".key"),
|
||||
secret: config.GetString(name + ".secret"),
|
||||
baseURL: baseURL,
|
||||
authURI: fmt.Sprintf("%s/%s", baseURL, config.GetString(name+".authURI")),
|
||||
accessTokenURI: fmt.Sprintf("%s/%s", baseURL, config.GetString(name+".accessTokenURI")),
|
||||
userURI: fmt.Sprintf("%s/%s", baseURL, config.GetString(name+".userURI")),
|
||||
callbackURL: config.GetString(name + ".callbackURI"),
|
||||
BaseURL: baseURL,
|
||||
AuthURI: fmt.Sprintf("%s/%s", baseURL, config.GetString(name+".authURI")),
|
||||
AccessTokenURI: fmt.Sprintf("%s/%s", baseURL, config.GetString(name+".accessTokenURI")),
|
||||
UserURI: fmt.Sprintf("%s/%s", baseURL, config.GetString(name+".userURI")),
|
||||
CallbackURL: config.GetString(name + ".callbackURI"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,11 +78,12 @@ func initProviders() {
|
||||
log.Info("- adding gitea provider")
|
||||
var p goth.Provider
|
||||
s := getProviderSetings("gitea")
|
||||
if s.authURI != "" {
|
||||
log.Infof("-- with custom settings %+v", s)
|
||||
p = gitea.NewCustomisedURL(s.key, s.secret, s.callbackURL, s.authURI, s.accessTokenURI, s.userURI)
|
||||
if s.AuthURI != "" {
|
||||
out, _ := json.MarshalIndent(s, "", " ")
|
||||
log.Infof("-- with custom settings %s", string(out))
|
||||
p = gitea.NewCustomisedURL(s.key, s.secret, s.CallbackURL, s.AuthURI, s.AccessTokenURI, s.UserURI)
|
||||
} else {
|
||||
p = gitea.New(s.key, s.secret, s.callbackURL)
|
||||
p = gitea.New(s.key, s.secret, s.CallbackURL)
|
||||
}
|
||||
providers = append(providers, p)
|
||||
}
|
||||
@ -80,11 +92,12 @@ func initProviders() {
|
||||
log.Info("- adding gitlab provider")
|
||||
var p goth.Provider
|
||||
s := getProviderSetings("gitlab")
|
||||
if s.authURI != "" {
|
||||
log.Infof("-- with custom settings %+v", s)
|
||||
p = gitlab.NewCustomisedURL(s.key, s.secret, s.callbackURL, s.authURI, s.accessTokenURI, s.userURI)
|
||||
if s.AuthURI != "" {
|
||||
out, _ := json.MarshalIndent(s, "", " ")
|
||||
log.Infof("-- with custom settings %s", string(out))
|
||||
p = gitlab.NewCustomisedURL(s.key, s.secret, s.CallbackURL, s.AuthURI, s.AccessTokenURI, s.UserURI)
|
||||
} else {
|
||||
p = gitlab.New(s.key, s.secret, s.callbackURL)
|
||||
p = gitlab.New(s.key, s.secret, s.CallbackURL)
|
||||
}
|
||||
providers = append(providers, p)
|
||||
}
|
||||
@ -93,7 +106,7 @@ func initProviders() {
|
||||
log.Info("- adding github provider")
|
||||
var p goth.Provider
|
||||
s := getProviderSetings("github")
|
||||
p = github.New(s.key, s.secret, s.callbackURL)
|
||||
p = github.New(s.key, s.secret, s.CallbackURL)
|
||||
providers = append(providers, p)
|
||||
}
|
||||
|
||||
@ -101,7 +114,7 @@ func initProviders() {
|
||||
log.Info("- adding bitbucket provider")
|
||||
var p goth.Provider
|
||||
s := getProviderSetings("bitbucket")
|
||||
p = bitbucket.New(s.key, s.secret, s.callbackURL)
|
||||
p = bitbucket.New(s.key, s.secret, s.CallbackURL)
|
||||
providers = append(providers, p)
|
||||
}
|
||||
|
||||
@ -109,37 +122,6 @@ func initProviders() {
|
||||
goth.UseProviders(providers...)
|
||||
}
|
||||
|
||||
const (
|
||||
script = `<!DOCTYPE html><html><head><script>
|
||||
if (!window.opener) {
|
||||
window.opener = {
|
||||
postMessage: function(action, origin) {
|
||||
console.log(action, origin);
|
||||
}
|
||||
}
|
||||
}
|
||||
(function(status, provider, result) {
|
||||
function recieveMessage(e) {
|
||||
console.log("Recieve message:", e);
|
||||
// send message to main window with da app
|
||||
console.log("Sending message:", "authorization:" + provider + ":" + status + ":" + result, e.origin)
|
||||
window.opener.postMessage(
|
||||
"authorization:" + provider + ":" + status + ":" + result,
|
||||
e.origin
|
||||
);
|
||||
}
|
||||
window.addEventListener("message", recieveMessage, false);
|
||||
|
||||
// Start handshare with parent
|
||||
console.log("Sending message:", "authorizing:" + provider, "*")
|
||||
window.opener.postMessage(
|
||||
"authorizing:" + provider,
|
||||
"*"
|
||||
);
|
||||
})(%#v, %#v, %#v)
|
||||
</script></head><body></body></html>`
|
||||
)
|
||||
|
||||
func main() {
|
||||
log = logrus.New().WithFields(logrus.Fields{
|
||||
"service": serviceName,
|
||||
@ -157,6 +139,8 @@ func main() {
|
||||
})
|
||||
|
||||
r.HandleFunc("/callback/{provider}", func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
|
||||
provider, err := gothic.GetProviderName(r)
|
||||
if err != nil {
|
||||
log.Errorf("callback: GetProviderName failed %v", err)
|
||||
@ -168,16 +152,18 @@ func main() {
|
||||
log.Errorf("callback: CompleteUserAuth failed %v", err)
|
||||
return
|
||||
}
|
||||
log.Info("logged in user")
|
||||
// t, _ := template.New("msg").Parse(msgTemplate)
|
||||
// t.Execute(w, fmt.Sprintf("Connected with UserID '%s'", user.UserID))
|
||||
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
result := fmt.Sprintf(`{"token":"%s", "provider":"%s"}`, user.AccessToken, user.Provider)
|
||||
log.Infof("logged in user to '%s'\n", vars["provider"])
|
||||
t, _ := template.New("res").Parse(resTemplate)
|
||||
|
||||
log.Info("details: %+v", user)
|
||||
w.Write([]byte(fmt.Sprintf(script, "success", provider, result)))
|
||||
data := struct {
|
||||
Provider string
|
||||
OAuthResult string
|
||||
}{
|
||||
Provider: fmt.Sprintf(`authorizing:%s`, provider),
|
||||
OAuthResult: fmt.Sprintf(`authorization:%s:%s:{"token":"%s", "provider":"%s"}`, provider, "success", user.AccessToken, user.Provider),
|
||||
}
|
||||
t.Execute(w, data)
|
||||
}).Methods("GET")
|
||||
|
||||
// redirect to correct auth/{provider} URL if Auth request is submited with a query param '&provider=X'
|
||||
@ -191,7 +177,9 @@ func main() {
|
||||
}).Methods("GET")
|
||||
|
||||
r.HandleFunc("/auth/{provider}", func(w http.ResponseWriter, r *http.Request) {
|
||||
log.Infof("handling auth provider request '%s'\n", r)
|
||||
vars := mux.Vars(r)
|
||||
log.Infof("handling auth provider request '%s'\n", vars["provider"])
|
||||
|
||||
if gothUser, err := gothic.CompleteUserAuth(w, r); err == nil {
|
||||
t, _ := template.New("msg").Parse(msgTemplate)
|
||||
t.Execute(w, fmt.Sprintf("Connected to existing session with UserID '%s'", gothUser.UserID))
|
||||
@ -201,7 +189,9 @@ func main() {
|
||||
}).Methods("GET")
|
||||
|
||||
r.HandleFunc("/logout/{provider}", func(w http.ResponseWriter, r *http.Request) {
|
||||
log.Infof("logout with '%s'\n", r)
|
||||
vars := mux.Vars(r)
|
||||
log.Infof("logout from '%s'\n", vars["provider"])
|
||||
|
||||
gothic.Logout(w, r)
|
||||
w.Header().Set("Location", "/")
|
||||
w.WriteHeader(http.StatusTemporaryRedirect)
|
||||
|
Loading…
x
Reference in New Issue
Block a user