mirror of
https://github.com/wavetermdev/wails.git
synced 2026-08-05 13:53:43 -07:00
[v3] Add oauth plugin
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
<!-- templates/index.html -->
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Google SignIn</title>
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"> <!-- load bulma css -->
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> <!-- load fontawesome -->
|
||||
</head>
|
||||
<body>
|
||||
<div id="main" class="container">
|
||||
<div class="jumbotron text-center text-success" style="padding-top:70px;">
|
||||
<h1><span class="fa fa-lock"></span> Social Authentication</h1>
|
||||
<p>Login or Register with:</p>
|
||||
<a data-wml-event="github-login" class="btn btn-primary"><span class="fa fa-github" style="color: #FFF"></span> SignIn with Github</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="details" class="text-center">
|
||||
<image id="logo" style="width:250px"></image>
|
||||
<h3 id="name" style="padding-top: 10px"></h3>
|
||||
</div>
|
||||
<script>
|
||||
window.wails.Events.On("wails:oauth:success", (event) => {
|
||||
document.getElementById("main").style.display = "none";
|
||||
document.getElementById("name").innerText = event.data.Name;
|
||||
document.getElementById("logo").src = event.data.AvatarURL;
|
||||
document.body.style.backgroundColor = "#000";
|
||||
document.body.style.color = "#FFF";
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,82 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"embed"
|
||||
_ "embed"
|
||||
"github.com/markbates/goth"
|
||||
"github.com/markbates/goth/providers/github"
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
"github.com/wailsapp/wails/v3/plugins/oauth"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
//go:embed assets
|
||||
var assets embed.FS
|
||||
|
||||
func main() {
|
||||
|
||||
oAuthPlugin := oauth.NewPlugin(oauth.Config{
|
||||
Providers: []goth.Provider{
|
||||
github.New(
|
||||
os.Getenv("clientkey"),
|
||||
os.Getenv("secret"),
|
||||
"http://localhost:9876/auth/github/callback",
|
||||
"email",
|
||||
"profile"),
|
||||
},
|
||||
})
|
||||
|
||||
app := application.New(application.Options{
|
||||
Name: "OAuth Demo",
|
||||
Description: "A demo of the oauth Plugin",
|
||||
Mac: application.MacOptions{
|
||||
ApplicationShouldTerminateAfterLastWindowClosed: true,
|
||||
},
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
},
|
||||
Plugins: map[string]application.Plugin{
|
||||
"github.com/wailsapp/wails/v3/plugins/oauth": oAuthPlugin,
|
||||
},
|
||||
})
|
||||
|
||||
oAuthWindow := app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{
|
||||
Title: "Login",
|
||||
Width: 600,
|
||||
Height: 850,
|
||||
Hidden: true,
|
||||
DisableResize: true,
|
||||
URL: "http://localhost:9876/auth/github",
|
||||
})
|
||||
|
||||
app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{
|
||||
Title: "OAuth Demo",
|
||||
DevToolsEnabled: true,
|
||||
OpenInspectorOnStartup: true,
|
||||
Mac: application.MacWindow{
|
||||
Backdrop: application.MacBackdropTranslucent,
|
||||
TitleBar: application.MacTitleBarHiddenInsetUnified,
|
||||
InvisibleTitleBarHeight: 50,
|
||||
},
|
||||
})
|
||||
|
||||
// Custom event handling
|
||||
app.Events.On(oauth.Success, func(e *application.WailsEvent) {
|
||||
oAuthWindow.Hide()
|
||||
})
|
||||
|
||||
app.Events.On(oauth.Error, func(e *application.WailsEvent) {
|
||||
oAuthWindow.Hide()
|
||||
})
|
||||
app.Events.On("github-login", func(e *application.WailsEvent) {
|
||||
oAuthPlugin.Start()
|
||||
oAuthWindow.Show()
|
||||
})
|
||||
|
||||
err := app.Run()
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
@@ -9,11 +9,14 @@ require (
|
||||
github.com/go-task/task/v3 v3.27.1
|
||||
github.com/google/go-cmp v0.5.9
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/gorilla/pat v1.0.1
|
||||
github.com/gorilla/sessions v1.2.1
|
||||
github.com/jackmordaunt/icns/v2 v2.2.1
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/leaanthony/clir v1.6.0
|
||||
github.com/leaanthony/gosod v1.0.3
|
||||
github.com/leaanthony/winicon v1.0.0
|
||||
github.com/markbates/goth v1.77.0
|
||||
github.com/matryer/is v1.4.0
|
||||
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2
|
||||
github.com/pkg/errors v0.9.1
|
||||
@@ -29,12 +32,17 @@ require (
|
||||
require (
|
||||
atomicgo.dev/cursor v0.1.1 // indirect
|
||||
atomicgo.dev/keyboard v0.2.8 // indirect
|
||||
cloud.google.com/go v0.67.0 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
||||
github.com/containerd/console v1.0.3 // indirect
|
||||
github.com/dustin/go-humanize v1.0.0 // indirect
|
||||
github.com/fatih/color v1.15.0 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||
github.com/golang/protobuf v1.4.2 // indirect
|
||||
github.com/gookit/color v1.5.2 // indirect
|
||||
github.com/gorilla/context v1.1.1 // indirect
|
||||
github.com/gorilla/mux v1.6.2 // indirect
|
||||
github.com/gorilla/securecookie v1.1.1 // indirect
|
||||
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
|
||||
github.com/joho/godotenv v1.5.1 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
@@ -58,10 +66,13 @@ require (
|
||||
golang.org/x/image v0.5.0 // indirect
|
||||
golang.org/x/mod v0.11.0 // indirect
|
||||
golang.org/x/net v0.7.0 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 // indirect
|
||||
golang.org/x/sync v0.3.0 // indirect
|
||||
golang.org/x/term v0.9.0 // indirect
|
||||
golang.org/x/text v0.7.0 // indirect
|
||||
golang.org/x/tools v0.2.0 // indirect
|
||||
google.golang.org/appengine v1.6.6 // indirect
|
||||
google.golang.org/protobuf v1.25.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
lukechampine.com/uint128 v1.2.0 // indirect
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
# oauth Plugin
|
||||
|
||||
This plugin provides the ability to initiate an OAuth authentication flow.
|
||||
|
||||
## Installation
|
||||
|
||||
Add the plugin to the `Plugins` option in the Applications options:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
"github.com/wailsapp/wails/v3/plugins/browser"
|
||||
)
|
||||
|
||||
func main() {
|
||||
oAuthPlugin := oauth.NewPlugin(oauth.Config{
|
||||
Providers: []goth.Provider{
|
||||
github.New(
|
||||
os.Getenv("clientkey"),
|
||||
os.Getenv("secret"),
|
||||
"http://localhost:9876/auth/github/callback",
|
||||
"email",
|
||||
"profile"),
|
||||
},
|
||||
})
|
||||
|
||||
app := application.New(application.Options{
|
||||
// ...
|
||||
Plugins: map[string]application.Plugin{
|
||||
"oauth": oAuthPlugin,
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Go
|
||||
|
||||
You can start the flow by calling `Start()` on the plugin instance:
|
||||
|
||||
```go
|
||||
app.Events.On("github-login", func(e *application.WailsEvent) {
|
||||
oAuthPlugin.Start()
|
||||
oAuthWindow.Show()
|
||||
})
|
||||
```
|
||||
|
||||
There is a working example of github auth in the `v3/examples` directory.
|
||||
|
||||
## Support
|
||||
|
||||
If you find a bug in this plugin, please raise a ticket on the Wails [Issue Tracker](https://github.com/wailsapp/wails/issues).
|
||||
@@ -0,0 +1,135 @@
|
||||
package oauth
|
||||
|
||||
import (
|
||||
"github.com/gorilla/pat"
|
||||
"github.com/gorilla/sessions"
|
||||
"github.com/markbates/goth"
|
||||
"github.com/markbates/goth/gothic"
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ---------------- Plugin Setup ----------------
|
||||
// This is the main plugin struct. It can be named anything you like.
|
||||
// It must implement the application.Plugin interface.
|
||||
// Both the Init() and Shutdown() methods are called synchronously when the app starts and stops.
|
||||
|
||||
const (
|
||||
Success = "wails:oauth:success"
|
||||
Error = "wails:oauth:error"
|
||||
)
|
||||
|
||||
type Plugin struct {
|
||||
config Config
|
||||
server *http.Server
|
||||
router *pat.Router
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
|
||||
// Address to bind the temporary webserver to
|
||||
// Defaults to localhost:9876
|
||||
Address string
|
||||
|
||||
// SessionSecret is the secret used to encrypt the session store.
|
||||
SessionSecret string
|
||||
|
||||
// MaxAge is the maximum age of the session in seconds.
|
||||
MaxAge int
|
||||
|
||||
// Providers is a list of goth providers to use.
|
||||
Providers []goth.Provider
|
||||
}
|
||||
|
||||
func NewPlugin(config Config) *Plugin {
|
||||
result := &Plugin{
|
||||
config: config,
|
||||
}
|
||||
if result.config.MaxAge == 0 {
|
||||
result.config.MaxAge = 86400 * 30 // 30 days
|
||||
}
|
||||
if result.config.Address == "" {
|
||||
result.config.Address = "localhost:9876"
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (p *Plugin) Shutdown() {
|
||||
if p.server != nil {
|
||||
p.server.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Plugin) Name() string {
|
||||
return "github.com/wailsapp/wails/v3/plugins/oauth"
|
||||
}
|
||||
|
||||
func (p *Plugin) Init(_ *application.App) error {
|
||||
|
||||
store := sessions.NewCookieStore([]byte(p.config.SessionSecret))
|
||||
store.MaxAge(p.config.MaxAge)
|
||||
store.Options.Path = "/"
|
||||
store.Options.HttpOnly = true
|
||||
store.Options.Secure = false
|
||||
|
||||
gothic.Store = store
|
||||
goth.UseProviders(p.config.Providers...)
|
||||
|
||||
p.router = pat.New()
|
||||
p.router.Get("/auth/{provider}/callback", func(res http.ResponseWriter, req *http.Request) {
|
||||
|
||||
println("Callback...")
|
||||
event := &application.WailsEvent{
|
||||
Name: Success,
|
||||
Sender: "",
|
||||
}
|
||||
user, err := gothic.CompleteUserAuth(res, req)
|
||||
if err != nil {
|
||||
event.Data = err.Error()
|
||||
event.Name = Error
|
||||
} else {
|
||||
event.Data = user
|
||||
}
|
||||
application.Get().Events.Emit(event)
|
||||
err = p.server.Close()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
p.server = nil
|
||||
})
|
||||
|
||||
p.router.Get("/auth/{provider}", func(res http.ResponseWriter, req *http.Request) {
|
||||
println("Authenticating...")
|
||||
gothic.BeginAuthHandler(res, req)
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Plugin) CallableByJS() []string {
|
||||
return []string{
|
||||
"Start",
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Plugin) InjectJS() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// ---------------- Plugin Methods ----------------
|
||||
|
||||
func (p *Plugin) Start() {
|
||||
if p.server != nil {
|
||||
println("Already listening")
|
||||
return
|
||||
}
|
||||
p.server = &http.Server{
|
||||
Addr: p.config.Address,
|
||||
Handler: p.router,
|
||||
}
|
||||
println("Starting server")
|
||||
|
||||
go p.server.ListenAndServe()
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
/**
|
||||
* Starts the oauth temporary server.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
function Start() {
|
||||
return wails.Plugin("oauth", "Start");
|
||||
}
|
||||
|
||||
export default {
|
||||
OAuth: {
|
||||
Start,
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
# This is the plugin definition file for the "oauth" plugin.
|
||||
|
||||
Name = "oauth"
|
||||
Description = "Provides oauth capabilities."
|
||||
Author = "Lea Anthony"
|
||||
Version = "v1.0.0"
|
||||
Website = "https://wails.io"
|
||||
Repository = "https://github.com/wailsapp/wails/v3/plugins/oauth"
|
||||
License = "MIT"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user