Skip to content

Commit

Permalink
all: implemented and documented examples
Browse files Browse the repository at this point in the history
  • Loading branch information
Aeneas Rekkas committed Jan 12, 2016
1 parent ce0a849 commit 8c625c9
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 141 deletions.
Binary file modified docs/authorize-code-grant.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
277 changes: 143 additions & 134 deletions fosite-example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ import (
"github.com/ory-am/fosite/handler/core/implicit"
"github.com/ory-am/fosite/handler/core/owner"
"github.com/ory-am/fosite/handler/core/refresh"
"github.com/parnurzeal/gorequest"
goauth "golang.org/x/oauth2"
"golang.org/x/oauth2/clientcredentials"
"log"
"net/http"
"net/url"
"time"
)

Expand Down Expand Up @@ -110,209 +112,216 @@ func fositeFactory() OAuth2Provider {
}

func main() {
http.HandleFunc("/", homeHandler)
http.HandleFunc("/callback", callbackHandler)
http.HandleFunc("/auth", authEndpoint)
http.HandleFunc("/token", tokenEndpoint)

http.HandleFunc("/", homeHandler)
http.HandleFunc("/callback", callbackHandler)
http.HandleFunc("/client", clientEndpoint)
http.HandleFunc("/owner", ownerEndpoint)
log.Fatal(http.ListenAndServe(":3846", nil))
}

func clientEndpoint(rw http.ResponseWriter, req *http.Request) {
rw.Write([]byte(fmt.Sprintf(`<h1>Client Credentials Grant</h1>`)))
token, err := appClientConf.Token(goauth.NoContext)
if err != nil {
rw.Write([]byte(fmt.Sprintf(`<p>I tried to get a token but received an error: %s</p>`, err.Error())))
return
}
rw.Write([]byte(fmt.Sprintf(`<p>Awesome, you just received an access token!<br><br>%s<br><br><strong>more info:</strong><br><br>%s</p>`, token.AccessToken, token)))
rw.Write([]byte(`<p><a href="/">Go back</a></p>`))
}
func tokenEndpoint(rw http.ResponseWriter, req *http.Request) {
ctx := NewContext()
var mySessionData session

func ownerEndpoint(rw http.ResponseWriter, req *http.Request) {
rw.Write([]byte(fmt.Sprintf(`<h1>Resource Owner Password Credentials Grant</h1>`)))
req.ParseForm()
if req.Form.Get("username") == "" || req.Form.Get("password") == "" {
rw.Write([]byte(`
<form method="post">
<ul>
<li>
<input type="text" name="username" placeholder="username"/> <small>try peter</small>
</li>
<li>
<input type="password" name="password" placeholder="password"/> <small>try foobar</small><br>
</li>
<li>
<input type="submit" />
</li>
</ul>
</form>
`))
rw.Write([]byte(`<p><a href="/">Go back</a></p>`))
accessRequest, err := oauth2.NewAccessRequest(ctx, req, &mySessionData)
if err != nil {
log.Printf("Error occurred in NewAccessRequest: %s\nStack: \n%s", err, err.(*errors.Error).ErrorStack())
oauth2.WriteAccessError(rw, accessRequest, err)
return
}

token, err := clientConf.PasswordCredentialsToken(goauth.NoContext, req.Form.Get("username"), req.Form.Get("password"))
response, err := oauth2.NewAccessResponse(ctx, req, accessRequest, &mySessionData)
if err != nil {
rw.Write([]byte(fmt.Sprintf(`<p>I tried to get a token but received an error: %s</p>`, err.Error())))
rw.Write([]byte(`<p><a href="/">Go back</a></p>`))
log.Printf("Error occurred in NewAccessResponse: %s\nStack: \n%s", err, err.(*errors.Error).ErrorStack())
oauth2.WriteAccessError(rw, accessRequest, err)
return
}
rw.Write([]byte(fmt.Sprintf(`<p>Awesome, you just received an access token!<br><br>%s<br><br><strong>more info:</strong><br><br>%s</p>`, token.AccessToken, token)))
rw.Write([]byte(`<p><a href="/">Go back</a></p>`))

oauth2.WriteAccessResponse(rw, accessRequest, response)
}

func tokenEndpoint(rw http.ResponseWriter, req *http.Request) {
func authEndpoint(rw http.ResponseWriter, req *http.Request) {
ctx := NewContext()
var mySessionData session

accessRequest, err := oauth2.NewAccessRequest(ctx, req, &mySessionData)
ar, err := oauth2.NewAuthorizeRequest(ctx, req)
if err != nil {
oauth2.WriteAccessError(rw, accessRequest, err)
log.Printf("Error occurred in NewAuthorizeRequest: %s\nStack: \n%s", err, err.(*errors.Error).ErrorStack())
oauth2.WriteAuthorizeError(rw, ar, err)
return
}

response, err := oauth2.NewAccessResponse(ctx, req, accessRequest, &mySessionData)
if req.Form.Get("username") != "peter" {
rw.Header().Set("Content-Type", "text/html; charset=utf-8")
rw.Write([]byte(`<h1>Login page</h1>`))
rw.Write([]byte(`
<p>Howdy! This is the log in page. For this example, it is enough to supply the username.</p>
<form method="post">
<input type="text" name="username" /> <small>try peter</small><br>
<input type="submit">
</form>
`))
return
}

// Normally, this would be the place where you would check if the user is logged in and gives his consent.
// For this test, let's assume that the user exists, is logged in, and gives his consent...

sess := &session{User: "peter"}
response, err := oauth2.NewAuthorizeResponse(ctx, req, ar, sess)
if err != nil {
oauth2.WriteAccessError(rw, accessRequest, err)
log.Printf("Error occurred in NewAuthorizeResponse: %s\nStack: \n%s", err, err.(*errors.Error).ErrorStack())
oauth2.WriteAuthorizeError(rw, ar, err)
return
}

oauth2.WriteAccessResponse(rw, accessRequest, response)
oauth2.WriteAuthorizeResponse(rw, ar, response)
}

//
// some views for easier navigation
//

func homeHandler(rw http.ResponseWriter, req *http.Request) {
rw.Write([]byte(fmt.Sprintf(`
<p>You can obtain an access token using various methods</p>
<ul>
<li>
<a href="%s">Authorize code grant</a>
</li>
<li>
<a href="%s">Implicit grant</a>
</li>
<li>
<a href="/client">Client credentials grant</a>
</li>
<li>
<a href="/owner">Resource owner password credentials grant</a>
</li>
<li>
<a href="/refresh">Refresh grant</a>
</li>
<li>
<a href="%s">Make an invalid request</a>
</li>
</ul>
`,
<p>You can obtain an access token using various methods</p>
<ul>
<li>
<a href="%s">Authorize code grant</a>
</li>
<li>
<a href="%s">Implicit grant</a>
</li>
<li>
<a href="/client">Client credentials grant</a>
</li>
<li>
<a href="/owner">Resource owner password credentials grant</a>
</li>
<li>
<a href="%s">Refresh grant</a>. <small>You will first see the login screen which is required to obtain a valid refresh token.</small>
</li>
<li>
<a href="%s">Make an invalid request</a>
</li>
</ul>`,
clientConf.AuthCodeURL("some-random-state-foobar"),
"http://localhost:3846/auth?client_id=my-client&redirect_uri=http%3A%2F%2Flocalhost%3A3846%2Fcallback&response_type=token&scope=fosite&state=some-random-state-foobar",
clientConf.AuthCodeURL("some-random-state-foobar"),
"/auth?client_id=my-client&scope=fosite&response_type=123&redirect_uri=http://localhost:3846/callback",
)))
}

func callbackHandler(rw http.ResponseWriter, req *http.Request) {
rw.Write([]byte(`<h1>Callback site</h1><a href="/">Go back</a>`))
rw.Header().Set("Content-Type", "text/html; charset=utf-8")
if req.URL.Query().Get("error") != "" {
rw.Write([]byte(fmt.Sprintf(`
<h1>Error!</h1>
Error: %s<br>
Description: %s<br>
<br>
<a href="/">Go back</a>
`,
rw.Write([]byte(fmt.Sprintf(`<h1>Error!</h1>
Error: %s<br>
Description: %s<br>
<br>`,
req.URL.Query().Get("error"),
req.URL.Query().Get("error_description"),
)))
return
}
rw.Write([]byte(fmt.Sprintf(`
<p>Amazing! You just got an authorize code!: %s</p>
<p>Click <a href="/">here to return</a> to the front page</p>
`,
req.URL.Query().Get("code"),
)))

if req.URL.Query().Get("refresh") != "" {
_, body, errs := gorequest.New().Post(clientConf.Endpoint.TokenURL).SetBasicAuth(clientConf.ClientID, clientConf.ClientSecret).SendString(url.Values{
"grant_type": {"refresh_token"},
"refresh_token": {req.URL.Query().Get("refresh")},
"scope": {"fosite"},
}.Encode()).End()
if len(errs) > 0 {
rw.Write([]byte(fmt.Sprintf(`<p>Could not refresh token %s</p>`, errs)))
return
}
rw.Write([]byte(fmt.Sprintf(`<p>Got a response from the refresh grant:<br><code>%s</code></p>`, body)))
return
}

if req.URL.Query().Get("code") == "" {
rw.Write([]byte(fmt.Sprintf(`
<p>Could not find the authorize code. If you've used the implicit grant, check the browser location bar for the
access token <small><a href="https://en.wikipedia.org/wiki/Fragment_identifier#Basics">(the server side does not have access to url fragments)</a></small></p>
`,
rw.Write([]byte(fmt.Sprintf(`<p>Could not find the authorize code. If you've used the implicit grant, check the
browser location bar for the
access token <small><a href="https://en.wikipedia.org/wiki/Fragment_identifier#Basics">(the server side does not have access to url fragments)</a></small>
</p>`,
)))

return
}

rw.Write([]byte(fmt.Sprintf(`<p>Amazing! You just got an authorize code!:<br><code>%s</code></p>
<p>Click <a href="/">here to return</a> to the front page</p>`,
req.URL.Query().Get("code"),
)))

token, err := clientConf.Exchange(goauth.NoContext, req.URL.Query().Get("code"))
if err != nil {
rw.Write([]byte(fmt.Sprintf(`
<p>
I tried to exchange the authorize code for an access token but it did not work but got error: %s
</p>
`,
err.Error(),
)))
rw.Write([]byte(fmt.Sprintf(`<p>I tried to exchange the authorize code for an access token but it did not work but got error: %s</p>`, err.Error())))
return
}

rw.Write([]byte(fmt.Sprintf(`
<p>Cool! You are now a proud token owner.<br>
<ul>
<li>
Access token: %s<br>
</li>
<li>
Refresh token: %s (click to refresh <a href="%s">here</a>)<br>
</li>
<li>
Extra info: %s<br>
</li>
</ul>
`,
rw.Write([]byte(fmt.Sprintf(`<p>Cool! You are now a proud token owner.<br>
<ul>
<li>
Access token:<br>
<code>%s</code>
</li>
<li>
Refresh token (click <a href="%s">here to use it</a>):<br>
<code>%s</code>
</li>
<li>
Extra info: <br>
<code>%s</code>
</li>
</ul>`,
token.AccessToken,
"?refresh="+url.QueryEscape(token.RefreshToken),
token.RefreshToken,
"",
token,
)))
}

func authEndpoint(rw http.ResponseWriter, req *http.Request) {
ctx := NewContext()

ar, err := oauth2.NewAuthorizeRequest(ctx, req)
func clientEndpoint(rw http.ResponseWriter, req *http.Request) {
rw.Write([]byte(fmt.Sprintf(`<h1>Client Credentials Grant</h1>`)))
token, err := appClientConf.Token(goauth.NoContext)
if err != nil {
log.Printf("Error occurred in authorize request part: %s\nStack: \n%s", err, err.(*errors.Error).ErrorStack())
oauth2.WriteAuthorizeError(rw, ar, err)
rw.Write([]byte(fmt.Sprintf(`<p>I tried to get a token but received an error: %s</p>`, err.Error())))
return
}
rw.Write([]byte(fmt.Sprintf(`<p>Awesome, you just received an access token!<br><br>%s<br><br><strong>more info:</strong><br><br>%s</p>`, token.AccessToken, token)))
rw.Write([]byte(`<p><a href="/">Go back</a></p>`))
}

if req.Form.Get("username") != "peter" {
rw.Header().Set("Content-Type", "text/html; charset=utf-8")
rw.Write([]byte(`
<p>
Howdy! This is the log in page. For this example, it is enough to supply the username.
</p>
<form method="post">
<input type="text" name="username" />
<input type="submit">
</form>
<em>ps: I heard that user "peter" is a valid username so why not try his name ;)</em>
`,
))
func ownerEndpoint(rw http.ResponseWriter, req *http.Request) {
rw.Write([]byte(fmt.Sprintf(`<h1>Resource Owner Password Credentials Grant</h1>`)))
req.ParseForm()
if req.Form.Get("username") == "" || req.Form.Get("password") == "" {
rw.Write([]byte(`<form method="post">
<ul>
<li>
<input type="text" name="username" placeholder="username"/> <small>try peter</small>
</li>
<li>
<input type="password" name="password" placeholder="password"/> <small>try foobar</small><br>
</li>
<li>
<input type="submit" />
</li>
</ul>
</form>`))
rw.Write([]byte(`<p><a href="/">Go back</a></p>`))
return
}

// Normally, this would be the place where you would check if the user is logged in and gives his consent.
// For this test, let's assume that the user exists, is logged in, and gives his consent...

sess := &session{User: "peter"}
response, err := oauth2.NewAuthorizeResponse(ctx, req, ar, sess)
token, err := clientConf.PasswordCredentialsToken(goauth.NoContext, req.Form.Get("username"), req.Form.Get("password"))
if err != nil {
log.Printf("Error occurred in authorize response part: %s\nStack: \n%s", err, err.(*errors.Error).ErrorStack())
oauth2.WriteAuthorizeError(rw, ar, err)
rw.Write([]byte(fmt.Sprintf(`<p>I tried to get a token but received an error: %s</p>`, err.Error())))
rw.Write([]byte(`<p><a href="/">Go back</a></p>`))
return
}

oauth2.WriteAuthorizeResponse(rw, ar, response)
rw.Write([]byte(fmt.Sprintf(`<p>Awesome, you just received an access token!<br><br>%s<br><br><strong>more info:</strong><br><br>%s</p>`, token.AccessToken, token)))
rw.Write([]byte(`<p><a href="/">Go back</a></p>`))
}
6 changes: 3 additions & 3 deletions handler/core/owner/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ func (c *ResourceOwnerPasswordCredentialsGrantHandler) ValidateTokenEndpointRequ
username := req.PostForm.Get("username")
password := req.PostForm.Get("password")
if username == "" || password == "" {
return fosite.ErrInvalidRequest
return errors.New(fosite.ErrInvalidRequest)
} else if err := c.Store.DoCredentialsAuthenticate(username, password); err == pkg.ErrNotFound {
return fosite.ErrInvalidRequest
return errors.New(fosite.ErrInvalidRequest)
} else if err != nil {
return fosite.ErrServerError
return errors.New(fosite.ErrServerError)
}

request.SetGrantTypeHandled("password")
Expand Down
Loading

0 comments on commit 8c625c9

Please sign in to comment.