1
0
mirror of https://github.com/kataras/iris.git synced 2025-12-30 08:17:18 +00:00

reorganization of _examples and add some new examples such as iris+groupcache+mysql+docker

Former-commit-id: ed635ee95de7160cde11eaabc0c1dcb0e460a620
This commit is contained in:
Gerasimos (Makis) Maropoulos
2020-06-07 15:26:06 +03:00
parent 9fdcb4c7fb
commit ed45c77be5
328 changed files with 4262 additions and 41621 deletions

View File

@@ -0,0 +1,57 @@
package main
import (
"time"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/middleware/basicauth"
)
func newApp() *iris.Application {
app := iris.New()
authConfig := basicauth.Config{
Users: map[string]string{"myusername": "mypassword", "mySecondusername": "mySecondpassword"},
Realm: "Authorization Required", // defaults to "Authorization Required"
Expires: time.Duration(30) * time.Minute,
}
authentication := basicauth.New(authConfig)
// to global app.Use(authentication) (or app.UseGlobal before the .Run)
// to routes
/*
app.Get("/mysecret", authentication, h)
*/
app.Get("/", func(ctx iris.Context) { ctx.Redirect("/admin") })
// to party
needAuth := app.Party("/admin", authentication)
{
//http://localhost:8080/admin
needAuth.Get("/", h)
// http://localhost:8080/admin/profile
needAuth.Get("/profile", h)
// http://localhost:8080/admin/settings
needAuth.Get("/settings", h)
}
return app
}
func main() {
app := newApp()
// open http://localhost:8080/admin
app.Listen(":8080")
}
func h(ctx iris.Context) {
username, password, _ := ctx.Request().BasicAuth()
// third parameter it will be always true because the middleware
// makes sure for that, otherwise this handler will not be executed.
ctx.Writef("%s %s:%s", ctx.Path(), username, password)
}

View File

@@ -0,0 +1,29 @@
package main
import (
"testing"
"github.com/kataras/iris/v12/httptest"
)
func TestBasicAuth(t *testing.T) {
app := newApp()
e := httptest.New(t, app)
// redirects to /admin without basic auth
e.GET("/").Expect().Status(httptest.StatusUnauthorized)
// without basic auth
e.GET("/admin").Expect().Status(httptest.StatusUnauthorized)
// with valid basic auth
e.GET("/admin").WithBasicAuth("myusername", "mypassword").Expect().
Status(httptest.StatusOK).Body().Equal("/admin myusername:mypassword")
e.GET("/admin/profile").WithBasicAuth("myusername", "mypassword").Expect().
Status(httptest.StatusOK).Body().Equal("/admin/profile myusername:mypassword")
e.GET("/admin/settings").WithBasicAuth("myusername", "mypassword").Expect().
Status(httptest.StatusOK).Body().Equal("/admin/settings myusername:mypassword")
// with invalid basic auth
e.GET("/admin/settings").WithBasicAuth("invalidusername", "invalidpassword").
Expect().Status(httptest.StatusUnauthorized)
}

407
_examples/auth/goth/main.go Normal file
View File

@@ -0,0 +1,407 @@
package main
// Any OAuth2 (even the pure golang/x/net/oauth2) package
// can be used with iris but at this example we will see the markbates' goth:
//
// $ go get github.com/markbates/goth/...
//
// This OAuth2 example works with sessions, so we will need
// to attach a session manager.
// Optionally: for even more secure session values,
// developers can use any third-party package to add a custom cookie encoder/decoder.
// At this example we will use the gorilla's securecookie:
//
// $ go get github.com/gorilla/securecookie
// Example of securecookie can be found at "sessions/securecookie" example folder.
// Notes:
// The whole example is converted by markbates/goth/example/main.go.
// It's tested with my own TWITTER application and it worked, even for localhost.
// I guess that everything else works as expected, all bugs reported by goth library's community
// are fixed in the time I wrote that example, have fun!
import (
"errors"
"os"
"sort"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/sessions"
"github.com/gorilla/securecookie" // optionally, used for session's encoder/decoder
"github.com/markbates/goth"
"github.com/markbates/goth/providers/amazon"
"github.com/markbates/goth/providers/auth0"
"github.com/markbates/goth/providers/bitbucket"
"github.com/markbates/goth/providers/box"
"github.com/markbates/goth/providers/dailymotion"
"github.com/markbates/goth/providers/deezer"
"github.com/markbates/goth/providers/digitalocean"
"github.com/markbates/goth/providers/discord"
"github.com/markbates/goth/providers/dropbox"
"github.com/markbates/goth/providers/facebook"
"github.com/markbates/goth/providers/fitbit"
"github.com/markbates/goth/providers/github"
"github.com/markbates/goth/providers/gitlab"
"github.com/markbates/goth/providers/gplus"
"github.com/markbates/goth/providers/heroku"
"github.com/markbates/goth/providers/instagram"
"github.com/markbates/goth/providers/intercom"
"github.com/markbates/goth/providers/lastfm"
"github.com/markbates/goth/providers/linkedin"
"github.com/markbates/goth/providers/meetup"
"github.com/markbates/goth/providers/onedrive"
"github.com/markbates/goth/providers/openidConnect"
"github.com/markbates/goth/providers/paypal"
"github.com/markbates/goth/providers/salesforce"
"github.com/markbates/goth/providers/slack"
"github.com/markbates/goth/providers/soundcloud"
"github.com/markbates/goth/providers/spotify"
"github.com/markbates/goth/providers/steam"
"github.com/markbates/goth/providers/stripe"
"github.com/markbates/goth/providers/twitch"
"github.com/markbates/goth/providers/twitter"
"github.com/markbates/goth/providers/uber"
"github.com/markbates/goth/providers/wepay"
"github.com/markbates/goth/providers/xero"
"github.com/markbates/goth/providers/yahoo"
"github.com/markbates/goth/providers/yammer"
)
var sessionsManager *sessions.Sessions
func init() {
// attach a session manager
cookieName := "mycustomsessionid"
hashKey := securecookie.GenerateRandomKey(64)
blockKey := securecookie.GenerateRandomKey(32)
secureCookie := securecookie.New(hashKey, blockKey)
sessionsManager = sessions.New(sessions.Config{
Cookie: cookieName,
Encoding: secureCookie,
AllowReclaim: true,
})
}
// These are some function helpers that you may use if you want
// GetProviderName is a function used to get the name of a provider
// for a given request. By default, this provider is fetched from
// the URL query string. If you provide it in a different way,
// assign your own function to this variable that returns the provider
// name for your request.
var GetProviderName = func(ctx iris.Context) (string, error) {
// try to get it from the url param "provider"
if p := ctx.URLParam("provider"); p != "" {
return p, nil
}
// try to get it from the url PATH parameter "{provider} or :provider or {provider:string} or {provider:alphabetical}"
if p := ctx.Params().Get("provider"); p != "" {
return p, nil
}
// try to get it from context's per-request storage
if p := ctx.Values().GetString("provider"); p != "" {
return p, nil
}
// if not found then return an empty string with the corresponding error
return "", errors.New("you must select a provider")
}
/*
BeginAuthHandler is a convenience handler for starting the authentication process.
It expects to be able to get the name of the provider from the query parameters
as either "provider" or ":provider".
BeginAuthHandler will redirect the user to the appropriate authentication end-point
for the requested provider.
See https://github.com/markbates/goth/examples/main.go to see this in action.
*/
func BeginAuthHandler(ctx iris.Context) {
url, err := GetAuthURL(ctx)
if err != nil {
ctx.StatusCode(iris.StatusBadRequest)
ctx.Writef("%v", err)
return
}
ctx.Redirect(url, iris.StatusTemporaryRedirect)
}
/*
GetAuthURL starts the authentication process with the requested provided.
It will return a URL that should be used to send users to.
It expects to be able to get the name of the provider from the query parameters
as either "provider" or ":provider" or from the context's value of "provider" key.
I would recommend using the BeginAuthHandler instead of doing all of these steps
yourself, but that's entirely up to you.
*/
func GetAuthURL(ctx iris.Context) (string, error) {
providerName, err := GetProviderName(ctx)
if err != nil {
return "", err
}
provider, err := goth.GetProvider(providerName)
if err != nil {
return "", err
}
sess, err := provider.BeginAuth(SetState(ctx))
if err != nil {
return "", err
}
url, err := sess.GetAuthURL()
if err != nil {
return "", err
}
session := sessionsManager.Start(ctx)
session.Set(providerName, sess.Marshal())
return url, nil
}
// SetState sets the state string associated with the given request.
// If no state string is associated with the request, one will be generated.
// This state is sent to the provider and can be retrieved during the
// callback.
var SetState = func(ctx iris.Context) string {
state := ctx.URLParam("state")
if len(state) > 0 {
return state
}
return "state"
}
// GetState gets the state returned by the provider during the callback.
// This is used to prevent CSRF attacks, see
// http://tools.ietf.org/html/rfc6749#section-10.12
var GetState = func(ctx iris.Context) string {
return ctx.URLParam("state")
}
/*
CompleteUserAuth does what it says on the tin. It completes the authentication
process and fetches all of the basic information about the user from the provider.
It expects to be able to get the name of the provider from the query parameters
as either "provider" or ":provider".
See https://github.com/markbates/goth/examples/main.go to see this in action.
*/
var CompleteUserAuth = func(ctx iris.Context) (goth.User, error) {
providerName, err := GetProviderName(ctx)
if err != nil {
return goth.User{}, err
}
provider, err := goth.GetProvider(providerName)
if err != nil {
return goth.User{}, err
}
session := sessionsManager.Start(ctx)
value := session.GetString(providerName)
if value == "" {
return goth.User{}, errors.New("session value for " + providerName + " not found")
}
sess, err := provider.UnmarshalSession(value)
if err != nil {
return goth.User{}, err
}
user, err := provider.FetchUser(sess)
if err == nil {
// user can be found with existing session data
return user, err
}
// get new token and retry fetch
_, err = sess.Authorize(provider, ctx.Request().URL.Query())
if err != nil {
return goth.User{}, err
}
session.Set(providerName, sess.Marshal())
return provider.FetchUser(sess)
}
// Logout invalidates a user session.
func Logout(ctx iris.Context) error {
providerName, err := GetProviderName(ctx)
if err != nil {
return err
}
session := sessionsManager.Start(ctx)
session.Delete(providerName)
return nil
}
// End of the "some function helpers".
func main() {
goth.UseProviders(
twitter.New(os.Getenv("TWITTER_KEY"), os.Getenv("TWITTER_SECRET"), "http://localhost:3000/auth/twitter/callback"),
// If you'd like to use authenticate instead of authorize in Twitter provider, use this instead.
// twitter.NewAuthenticate(os.Getenv("TWITTER_KEY"), os.Getenv("TWITTER_SECRET"), "http://localhost:3000/auth/twitter/callback"),
facebook.New(os.Getenv("FACEBOOK_KEY"), os.Getenv("FACEBOOK_SECRET"), "http://localhost:3000/auth/facebook/callback"),
fitbit.New(os.Getenv("FITBIT_KEY"), os.Getenv("FITBIT_SECRET"), "http://localhost:3000/auth/fitbit/callback"),
gplus.New(os.Getenv("GPLUS_KEY"), os.Getenv("GPLUS_SECRET"), "http://localhost:3000/auth/gplus/callback"),
github.New(os.Getenv("GITHUB_KEY"), os.Getenv("GITHUB_SECRET"), "http://localhost:3000/auth/github/callback"),
spotify.New(os.Getenv("SPOTIFY_KEY"), os.Getenv("SPOTIFY_SECRET"), "http://localhost:3000/auth/spotify/callback"),
linkedin.New(os.Getenv("LINKEDIN_KEY"), os.Getenv("LINKEDIN_SECRET"), "http://localhost:3000/auth/linkedin/callback"),
lastfm.New(os.Getenv("LASTFM_KEY"), os.Getenv("LASTFM_SECRET"), "http://localhost:3000/auth/lastfm/callback"),
twitch.New(os.Getenv("TWITCH_KEY"), os.Getenv("TWITCH_SECRET"), "http://localhost:3000/auth/twitch/callback"),
dropbox.New(os.Getenv("DROPBOX_KEY"), os.Getenv("DROPBOX_SECRET"), "http://localhost:3000/auth/dropbox/callback"),
digitalocean.New(os.Getenv("DIGITALOCEAN_KEY"), os.Getenv("DIGITALOCEAN_SECRET"), "http://localhost:3000/auth/digitalocean/callback", "read"),
bitbucket.New(os.Getenv("BITBUCKET_KEY"), os.Getenv("BITBUCKET_SECRET"), "http://localhost:3000/auth/bitbucket/callback"),
instagram.New(os.Getenv("INSTAGRAM_KEY"), os.Getenv("INSTAGRAM_SECRET"), "http://localhost:3000/auth/instagram/callback"),
intercom.New(os.Getenv("INTERCOM_KEY"), os.Getenv("INTERCOM_SECRET"), "http://localhost:3000/auth/intercom/callback"),
box.New(os.Getenv("BOX_KEY"), os.Getenv("BOX_SECRET"), "http://localhost:3000/auth/box/callback"),
salesforce.New(os.Getenv("SALESFORCE_KEY"), os.Getenv("SALESFORCE_SECRET"), "http://localhost:3000/auth/salesforce/callback"),
amazon.New(os.Getenv("AMAZON_KEY"), os.Getenv("AMAZON_SECRET"), "http://localhost:3000/auth/amazon/callback"),
yammer.New(os.Getenv("YAMMER_KEY"), os.Getenv("YAMMER_SECRET"), "http://localhost:3000/auth/yammer/callback"),
onedrive.New(os.Getenv("ONEDRIVE_KEY"), os.Getenv("ONEDRIVE_SECRET"), "http://localhost:3000/auth/onedrive/callback"),
// Pointed localhost.com to http://localhost:3000/auth/yahoo/callback through proxy as yahoo
// does not allow to put custom ports in redirection uri
yahoo.New(os.Getenv("YAHOO_KEY"), os.Getenv("YAHOO_SECRET"), "http://localhost.com"),
slack.New(os.Getenv("SLACK_KEY"), os.Getenv("SLACK_SECRET"), "http://localhost:3000/auth/slack/callback"),
stripe.New(os.Getenv("STRIPE_KEY"), os.Getenv("STRIPE_SECRET"), "http://localhost:3000/auth/stripe/callback"),
wepay.New(os.Getenv("WEPAY_KEY"), os.Getenv("WEPAY_SECRET"), "http://localhost:3000/auth/wepay/callback", "view_user"),
// By default paypal production auth urls will be used, please set PAYPAL_ENV=sandbox as environment variable for testing
// in sandbox environment
paypal.New(os.Getenv("PAYPAL_KEY"), os.Getenv("PAYPAL_SECRET"), "http://localhost:3000/auth/paypal/callback"),
steam.New(os.Getenv("STEAM_KEY"), "http://localhost:3000/auth/steam/callback"),
heroku.New(os.Getenv("HEROKU_KEY"), os.Getenv("HEROKU_SECRET"), "http://localhost:3000/auth/heroku/callback"),
uber.New(os.Getenv("UBER_KEY"), os.Getenv("UBER_SECRET"), "http://localhost:3000/auth/uber/callback"),
soundcloud.New(os.Getenv("SOUNDCLOUD_KEY"), os.Getenv("SOUNDCLOUD_SECRET"), "http://localhost:3000/auth/soundcloud/callback"),
gitlab.New(os.Getenv("GITLAB_KEY"), os.Getenv("GITLAB_SECRET"), "http://localhost:3000/auth/gitlab/callback"),
dailymotion.New(os.Getenv("DAILYMOTION_KEY"), os.Getenv("DAILYMOTION_SECRET"), "http://localhost:3000/auth/dailymotion/callback", "email"),
deezer.New(os.Getenv("DEEZER_KEY"), os.Getenv("DEEZER_SECRET"), "http://localhost:3000/auth/deezer/callback", "email"),
discord.New(os.Getenv("DISCORD_KEY"), os.Getenv("DISCORD_SECRET"), "http://localhost:3000/auth/discord/callback", discord.ScopeIdentify, discord.ScopeEmail),
meetup.New(os.Getenv("MEETUP_KEY"), os.Getenv("MEETUP_SECRET"), "http://localhost:3000/auth/meetup/callback"),
// Auth0 allocates domain per customer, a domain must be provided for auth0 to work
auth0.New(os.Getenv("AUTH0_KEY"), os.Getenv("AUTH0_SECRET"), "http://localhost:3000/auth/auth0/callback", os.Getenv("AUTH0_DOMAIN")),
xero.New(os.Getenv("XERO_KEY"), os.Getenv("XERO_SECRET"), "http://localhost:3000/auth/xero/callback"),
)
// OpenID Connect is based on OpenID Connect Auto Discovery URL (https://openid.net/specs/openid-connect-discovery-1_0-17.html)
// because the OpenID Connect provider initialize it self in the New(), it can return an error which should be handled or ignored
// ignore the error for now
openidConnect, _ := openidConnect.New(os.Getenv("OPENID_CONNECT_KEY"), os.Getenv("OPENID_CONNECT_SECRET"), "http://localhost:3000/auth/openid-connect/callback", os.Getenv("OPENID_CONNECT_DISCOVERY_URL"))
if openidConnect != nil {
goth.UseProviders(openidConnect)
}
m := make(map[string]string)
m["amazon"] = "Amazon"
m["bitbucket"] = "Bitbucket"
m["box"] = "Box"
m["dailymotion"] = "Dailymotion"
m["deezer"] = "Deezer"
m["digitalocean"] = "Digital Ocean"
m["discord"] = "Discord"
m["dropbox"] = "Dropbox"
m["facebook"] = "Facebook"
m["fitbit"] = "Fitbit"
m["github"] = "Github"
m["gitlab"] = "Gitlab"
m["soundcloud"] = "SoundCloud"
m["spotify"] = "Spotify"
m["steam"] = "Steam"
m["stripe"] = "Stripe"
m["twitch"] = "Twitch"
m["uber"] = "Uber"
m["wepay"] = "Wepay"
m["yahoo"] = "Yahoo"
m["yammer"] = "Yammer"
m["gplus"] = "Google Plus"
m["heroku"] = "Heroku"
m["instagram"] = "Instagram"
m["intercom"] = "Intercom"
m["lastfm"] = "Last FM"
m["linkedin"] = "Linkedin"
m["onedrive"] = "Onedrive"
m["paypal"] = "Paypal"
m["twitter"] = "Twitter"
m["salesforce"] = "Salesforce"
m["slack"] = "Slack"
m["meetup"] = "Meetup.com"
m["auth0"] = "Auth0"
m["openid-connect"] = "OpenID Connect"
m["xero"] = "Xero"
var keys []string
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
providerIndex := &ProviderIndex{Providers: keys, ProvidersMap: m}
// create our app,
// set a view
// set sessions
// and setup the router for the showcase
app := iris.New()
// attach and build our templates
app.RegisterView(iris.HTML("./templates", ".html"))
// start of the router
app.Get("/auth/{provider}/callback", func(ctx iris.Context) {
user, err := CompleteUserAuth(ctx)
if err != nil {
ctx.StatusCode(iris.StatusInternalServerError)
ctx.Writef("%v", err)
return
}
ctx.ViewData("", user)
if err := ctx.View("user.html"); err != nil {
ctx.Writef("%v", err)
}
})
app.Get("/logout/{provider}", func(ctx iris.Context) {
Logout(ctx)
ctx.Redirect("/", iris.StatusTemporaryRedirect)
})
app.Get("/auth/{provider}", func(ctx iris.Context) {
// try to get the user without re-authenticating
if gothUser, err := CompleteUserAuth(ctx); err == nil {
ctx.ViewData("", gothUser)
if err := ctx.View("user.html"); err != nil {
ctx.Writef("%v", err)
}
} else {
BeginAuthHandler(ctx)
}
})
app.Get("/", func(ctx iris.Context) {
ctx.ViewData("", providerIndex)
if err := ctx.View("index.html"); err != nil {
ctx.Writef("%v", err)
}
})
// http://localhost:3000
app.Listen("localhost:3000")
}
type ProviderIndex struct {
Providers []string
ProvidersMap map[string]string
}

View File

@@ -0,0 +1,3 @@
{{range $key,$value:=.Providers}}
<p><a href="/auth/{{$value}}">Log in with {{index $.ProvidersMap $value}}</a></p>
{{end}}

View File

@@ -0,0 +1,11 @@
<p><a href="/logout/{{.Provider}}">logout</a></p>
<p>Name: {{.Name}} [{{.LastName}}, {{.FirstName}}]</p>
<p>Email: {{.Email}}</p>
<p>NickName: {{.NickName}}</p>
<p>Location: {{.Location}}</p>
<p>AvatarURL: {{.AvatarURL}} <img src="{{.AvatarURL}}"></p>
<p>Description: {{.Description}}</p>
<p>UserID: {{.UserID}}</p>
<p>AccessToken: {{.AccessToken}}</p>
<p>ExpiresAt: {{.ExpiresAt}}</p>
<p>RefreshToken: {{.RefreshToken}}</p>

View File

@@ -0,0 +1,3 @@
# https://docs.hcaptcha.com/#localdev
# Add to the end of your hosts file, e.g. on windows: C:/windows/system32/drivers/etc/hosts
127.0.0.1 yourdomain.com

View File

@@ -0,0 +1,46 @@
package main
import (
"os"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/middleware/hcaptcha"
)
// Get the following values from: https://dashboard.hcaptcha.com
// Also, check: https://docs.hcaptcha.com/#localdev to test on local environment.
var (
siteKey = os.Getenv("HCAPTCHA-SITE-KEY")
secretKey = os.Getenv("HCAPTCHA-SECRET-KEY")
)
func main() {
app := iris.New()
app.RegisterView(iris.HTML("./templates", ".html"))
hCaptcha := hcaptcha.New(secretKey)
app.Get("/register", registerForm)
app.Post("/register", hCaptcha, register) // See `hcaptcha.SiteVerify` for manual validation too.
app.Logger().Infof("SiteKey = %s\tSecretKey = %s",
siteKey, secretKey)
// GET: http://yourdomain.com/register
app.Listen(":80")
}
func register(ctx iris.Context) {
hcaptchaResp, ok := hcaptcha.Get(ctx)
if !ok {
ctx.StatusCode(iris.StatusUnauthorized)
ctx.WriteString("Are you a bot?")
return
}
ctx.Writef("Register action here...action was asked by a Human.\nResponse value is: %#+v", hcaptchaResp)
}
func registerForm(ctx iris.Context) {
ctx.ViewData("SiteKey", siteKey)
ctx.View("register_form.html")
}

View File

@@ -0,0 +1,18 @@
<html>
<head>
<title>hCaptcha Demo</title>
<script src="https://hcaptcha.com/1/api.js" async defer></script>
</head>
<body>
<form action="/register" method="POST">
<input type="text" name="email" placeholder="Email" />
<input type="password" name="password" placeholder="Password" />
<div class="h-captcha" data-sitekey="{{ .SiteKey }}"></div>
<br />
<input type="submit" value="Submit" />
</form>
</body>
</html>

View File

@@ -0,0 +1,29 @@
# Generate RSA
```sh
$ openssl genrsa -des3 -out private_rsa.pem 2048
```
```go
b, err := ioutil.ReadFile("./private_rsa.pem")
if err != nil {
panic(err)
}
key := jwt.MustParseRSAPrivateKey(b, []byte("pass"))
```
OR
```go
import "crypto/rand"
import "crypto/rsa"
key, err := rsa.GenerateKey(rand.Reader, 2048)
```
# Generate Ed25519
```sh
$ openssl genpkey -algorithm Ed25519 -out private_ed25519.pem
$ openssl req -x509 -key private_ed25519.pem -out cert_ed25519.pem -days 365
```

155
_examples/auth/jwt/main.go Normal file
View File

@@ -0,0 +1,155 @@
package main
import (
"time"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/middleware/jwt"
)
// UserClaims a custom claims structure. You can just use jwt.Claims too.
type UserClaims struct {
jwt.Claims
Username string
}
func main() {
// Get keys from system's environment variables
// JWT_SECRET (for signing and verification) and JWT_SECRET_ENC(for encryption and decryption),
// or defaults to "secret" and "itsa16bytesecret" respectfully.
//
// Use the `jwt.New` instead for more flexibility, if necessary.
j := jwt.HMAC(15*time.Minute, "secret", "itsa16bytesecret")
app := iris.New()
app.Logger().SetLevel("debug")
app.Get("/authenticate", func(ctx iris.Context) {
standardClaims := jwt.Claims{Issuer: "an-issuer", Audience: jwt.Audience{"an-audience"}}
// NOTE: if custom claims then the `j.Expiry(claims)` (or jwt.Expiry(duration, claims))
// MUST be called in order to set the expiration time.
customClaims := UserClaims{
Claims: j.Expiry(standardClaims),
Username: "kataras",
}
j.WriteToken(ctx, customClaims)
})
userRouter := app.Party("/user")
{
// userRouter.Use(j.Verify)
// userRouter.Get("/", func(ctx iris.Context) {
// var claims UserClaims
// if err := jwt.ReadClaims(ctx, &claims); err != nil {
// // Validation-only errors, the rest are already
// // checked on `j.Verify` middleware.
// ctx.StopWithStatus(iris.StatusUnauthorized)
// return
// }
//
// ctx.Writef("Claims: %#+v\n", claims)
// })
//
// OR:
userRouter.Get("/", func(ctx iris.Context) {
var claims UserClaims
if err := j.VerifyToken(ctx, &claims); err != nil {
ctx.StopWithStatus(iris.StatusUnauthorized)
return
}
ctx.Writef("Claims: %#+v\n", claims)
})
}
app.Listen(":8080")
}
/*
func default_RSA_Example() {
j := jwt.RSA(15*time.Minute)
}
Same as:
func load_File_Or_Generate_RSA_Example() {
signKey, err := jwt.LoadRSA("jwt_sign.key", 2048)
if err != nil {
panic(err)
}
j, err := jwt.New(15*time.Minute, jwt.RS256, signKey)
if err != nil {
panic(err)
}
encKey, err := jwt.LoadRSA("jwt_enc.key", 2048)
if err != nil {
panic(err)
}
err = j.WithEncryption(jwt.A128CBCHS256, jwt.RSA15, encKey)
if err != nil {
panic(err)
}
}
*/
/*
func hmac_Example() {
// hmac
key := []byte("secret")
j, err := jwt.New(15*time.Minute, jwt.HS256, key)
if err != nil {
panic(err)
}
// OPTIONAL encryption:
encryptionKey := []byte("itsa16bytesecret")
err = j.WithEncryption(jwt.A128GCM, jwt.DIRECT, encryptionKey)
if err != nil {
panic(err)
}
}
*/
/*
func load_From_File_With_Password_Example() {
b, err := ioutil.ReadFile("./rsa_password_protected.key")
if err != nil {
panic(err)
}
signKey,err := jwt.ParseRSAPrivateKey(b, []byte("pass"))
if err != nil {
panic(err)
}
j, err := jwt.New(15*time.Minute, jwt.RS256, signKey)
if err != nil {
panic(err)
}
}
*/
/*
func generate_RSA_Example() {
signKey, err := rsa.GenerateKey(rand.Reader, 4096)
if err != nil {
panic(err)
}
encryptionKey, err := rsa.GenerateKey(rand.Reader, 4096)
if err != nil {
panic(err)
}
j, err := jwt.New(15*time.Minute, jwt.RS512, signKey)
if err != nil {
panic(err)
}
err = j.WithEncryption(jwt.A128CBCHS256, jwt.RSA15, encryptionKey)
if err != nil {
panic(err)
}
}
*/

View File

@@ -0,0 +1,30 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,6B0BC214C94124FE
lAM48DEM/GdCDimr9Vhi+fSHLgduDb0l2BA4uhILgNby51jxY/4X3IqM6f3ImKX7
cEd9OBug+pwIugB0UW0L0f5Pd59Ovpiaz3xLci1/19ehYnMqsuP3YAnJm40hT5VP
p0gWRiR415PJ0fPeeJPFx5IsqvkTJ30LWZHUZX4EkdcL5L8PrVbmthGDbLh+OcMc
LzoP8eTglzlZF03nyvAol6+p2eZtvOJLu8nWG25q17kyBx6kEiCsWFcUBTX9G7sH
CM3naByDijqZXE/XXtmTMLSRRnlk7Q5WLxClroHlUP9y8BQFMo2TW4Z+vNjHUkc1
77ghabX1704bAlIE8LLZJKrm/C5+VKyV6117SVG/2bc4036Y5rStXpANbk1j4K0x
ADvpRhuTpifaogdvJP+8eXBdl841MQMRzWuZHp6UNYYQegoV9C+KHyJx4UPjZyzd
gblZmKgU+BsX3mV6MLhJtd6dheLZtpBsAlSstJxzmgwqz9faONYEGeItXO+NnxbA
mxAp/mI+Fz2jfgYlWjwkyPPzD4k/ZMMzB4XLkKKs9XaxUtTomiDkuYZfnABhxt73
xBy40V1rb/NyeW80pk1zEHM6Iy/48ETSp9U3k9sSOXjMhYbPXgxDtimV8w0qGFAo
2Tif7ZuaiuC38rOkoHK9C6vy2Dp8lQZ+QBnUKLeFsyhq9CaqSdnyUTMj3oEZXXf+
TqqeO+PTtl7JaNfGRq6/aMZqxACHkyVUvYvjZzx07CJ2fr+OtNqxallM6Oc/o9NZ
5u7lpgrYaKM/b67q0d2X/AoxR5zrZuM8eam3acD1PwHFQKbJWuFNmjWtnlZNuR3X
fZEmxIKwDlup8TxFcqbbZtPHuQA2mTMTqfRkf8oPSO+N6NNaUpb0ignYyA7Eu5GT
b02d/oNLETMikxUxntMSH7GhuOpfJyELz8krYTttbJ+a93h4wBeYW2+LyAr/cRLB
mbtKLtaN7f3FaOSnu8e0+zlJ7xglHPXqblRL9q6ZDM5UJtJD4rA7LPZHk/0Y1Kb6
hBh1qMDu0r3IV4X7MDacvxw7aa7D8TyXJiFSvxykVhds+ndjIe51Ics5908+lev3
nwE69PLMwyqe2vvE2oDwao4XJuBLCHjcv/VagRSz/XQGMbZqb3L6unyd3UPl8JjP
ovipNwM4rFnE54uiUUeki7TZGDYO72vQcSaLrmbeAWc2m202+rqLz0WMm6HpPmCv
IgexpX2MnIeHJ3+BlEjA2u+S6xNSD7qHGk2pb7DD8nRvUdSHAHeaQbrkEfEhhR2Q
Dw5gdw1JyQ0UKBl5ndn/1Ub2Asl016lZjpqHyMIVS4tFixACDsihEYMmq/zQmTj4
8oBZTU+fycN/KiGKZBsqxIwgYIeMz/GfvoyN5m57l6fwEZALVpveI1pP4fiZB/Z8
xLKa5JK6L10lAD1YHWc1dPhamf9Sb3JwN2CFtGvjOJ/YjAZu3jJoxi40DtRkE3Rh
HI8Cbx1OORzoo0kO0vy42rz5qunYyVmEzPKtOj+YjVEhVJ85yJZ9bTZtuyqMv8mH
cnwEeIFK8cmm9asbVzQGDwN/UGB4cO3LrMX1RYk4GRttTGlp0729BbmZmu00RnD/
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1,118 @@
package main
import (
"fmt"
"log"
"strings"
"github.com/kataras/iris/v12"
permissions "github.com/xyproto/permissionbolt"
// * PostgreSQL support:
// permissions "github.com/xyproto/pstore" and
// perm, err := permissions.New(...)
//
// * MariaDB/MySQL support:
// permissions "github.com/xyproto/permissionsql" and
// perm, err := permissions.New/NewWithDSN(...)
// * Redis support:
// permissions "github.com/xyproto/permissions2"
// perm, err := permissions.New2()
// * Bolt support (this one):
// permissions "github.com/xyproto/permissionbolt" and
// perm, err := permissions.New(...)
)
func main() {
app := iris.New()
app.Logger().SetLevel("debug")
// New permissions middleware.
perm, err := permissions.New()
if err != nil {
log.Fatalln(err)
}
// Blank slate, no default permissions
// perm.Clear()
// Set up a middleware handler for Iris, with a custom "permission denied" message.
permissionHandler := func(ctx iris.Context) {
// Check if the user has the right admin/user rights
if perm.Rejected(ctx.ResponseWriter(), ctx.Request()) {
// Deny the request, don't call other middleware handlers
ctx.StopWithText(iris.StatusForbidden, "Permission denied!")
return
}
// Call the next middleware handler
ctx.Next()
}
// Register the permissions middleware
app.Use(permissionHandler)
// Get the userstate, used in the handlers below
userstate := perm.UserState()
app.Get("/", func(ctx iris.Context) {
msg := ""
msg += fmt.Sprintf("Has user bob: %v\n", userstate.HasUser("bob"))
msg += fmt.Sprintf("Logged in on server: %v\n", userstate.IsLoggedIn("bob"))
msg += fmt.Sprintf("Is confirmed: %v\n", userstate.IsConfirmed("bob"))
msg += fmt.Sprintf("Username stored in cookies (or blank): %v\n", userstate.Username(ctx.Request()))
msg += fmt.Sprintf("Current user is logged in, has a valid cookie and *user rights*: %v\n", userstate.UserRights(ctx.Request()))
msg += fmt.Sprintf("Current user is logged in, has a valid cookie and *admin rights*: %v\n", userstate.AdminRights(ctx.Request()))
msg += fmt.Sprintln("\nTry: /register, /confirm, /remove, /login, /logout, /makeadmin, /clear, /data and /admin")
ctx.WriteString(msg)
})
app.Get("/register", func(ctx iris.Context) {
userstate.AddUser("bob", "hunter1", "bob@zombo.com")
ctx.Writef("User bob was created: %v\n", userstate.HasUser("bob"))
})
app.Get("/confirm", func(ctx iris.Context) {
userstate.MarkConfirmed("bob")
ctx.Writef("User bob was confirmed: %v\n", userstate.IsConfirmed("bob"))
})
app.Get("/remove", func(ctx iris.Context) {
userstate.RemoveUser("bob")
ctx.Writef("User bob was removed: %v\n", !userstate.HasUser("bob"))
})
app.Get("/login", func(ctx iris.Context) {
// Headers will be written, for storing a cookie
userstate.Login(ctx.ResponseWriter(), "bob")
ctx.Writef("bob is now logged in: %v\n", userstate.IsLoggedIn("bob"))
})
app.Get("/logout", func(ctx iris.Context) {
userstate.Logout("bob")
ctx.Writef("bob is now logged out: %v\n", !userstate.IsLoggedIn("bob"))
})
app.Get("/makeadmin", func(ctx iris.Context) {
userstate.SetAdminStatus("bob")
ctx.Writef("bob is now administrator: %v\n", userstate.IsAdmin("bob"))
})
app.Get("/clear", func(ctx iris.Context) {
userstate.ClearCookie(ctx.ResponseWriter())
ctx.WriteString("Clearing cookie")
})
app.Get("/data", func(ctx iris.Context) {
ctx.WriteString("user page that only logged in users must see!")
})
app.Get("/admin", func(ctx iris.Context) {
ctx.WriteString("super secret information that only logged in administrators must see!\n\n")
if usernames, err := userstate.AllUsernames(); err == nil {
ctx.Writef("list of all users: %s" + strings.Join(usernames, ", "))
}
})
// Serve
app.Listen(":8080")
}

View File

@@ -0,0 +1,44 @@
package main
import (
"fmt"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/middleware/recaptcha"
)
// keys should be obtained by https://www.google.com/recaptcha
const (
recaptchaPublic = "6Lf3WywUAAAAAKNfAm5DP2J5ahqedtZdHTYaKkJ6"
recaptchaSecret = "6Lf3WywUAAAAAJpArb8nW_LCL_PuPuokmEABFfgw"
)
func main() {
app := iris.New()
r := recaptcha.New(recaptchaSecret)
app.Get("/comment", showRecaptchaForm)
// pass the middleware before the main handler or use the `recaptcha.SiteVerify`.
app.Post("/comment", r, postComment)
app.Listen(":8080")
}
var htmlForm = `<form action="/comment" method="POST">
<script src="https://www.google.com/recaptcha/api.js"></script>
<div class="g-recaptcha" data-sitekey="%s"></div>
<input type="submit" name="button" value="Verify">
</form>`
func showRecaptchaForm(ctx iris.Context) {
contents := fmt.Sprintf(htmlForm, recaptchaPublic)
ctx.HTML(contents)
}
func postComment(ctx iris.Context) {
// [...]
ctx.JSON(iris.Map{"success": true})
}

View File

@@ -0,0 +1,40 @@
package main
import (
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/middleware/recaptcha"
)
// keys should be obtained by https://www.google.com/recaptcha
const (
recaptchaPublic = ""
recaptchaSecret = ""
)
func showRecaptchaForm(ctx iris.Context, path string) {
ctx.HTML(recaptcha.GetFormHTML(recaptchaPublic, path))
}
func main() {
app := iris.New()
// On both Get and Post on this example, so you can easly
// use a single route to show a form and the main subject if recaptcha's validation result succeed.
app.HandleMany("GET POST", "/", func(ctx iris.Context) {
if ctx.Method() == iris.MethodGet {
showRecaptchaForm(ctx, "/")
return
}
result := recaptcha.SiteVerify(ctx, recaptchaSecret)
if !result.Success {
/* redirect here if u want or do nothing */
ctx.HTML("<b> failed please try again </b>")
return
}
ctx.Writef("succeed.")
})
app.Listen(":8080")
}