-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Adds scope record for scope lists and scope strings * Adds an optional scope using add_scope * Adds ScopeList test * Adds example for client credentials --------- Co-authored-by: Adam Davies <[email protected]>
- Loading branch information
1 parent
562ce20
commit 4eda668
Showing
4 changed files
with
196 additions
and
2 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 |
---|---|---|
@@ -0,0 +1,80 @@ | ||
# Usage Examples | ||
|
||
## Prerequisites | ||
|
||
To make use of the example code below, you will first need to follow your Identity Provider's | ||
process for creating a client id and client secret and obtaining the token request URI and | ||
scope value(s). | ||
|
||
## Authorization Code | ||
|
||
``` | ||
// TODO | ||
``` | ||
|
||
## Client Credentials | ||
|
||
> **TIP** | ||
> | ||
> Verify how your authorization server handles the access token scopes for client | ||
> credentials flow. If it is not required to send a scope in the request, use the | ||
> DefaultScope parameterless constructor to omit the scope parameter from the request. | ||
> | ||
> See the [Scope][cc1] type for more details. | ||
```gleam | ||
import gleam/hackney | ||
import gleam/io | ||
import gleam/result | ||
import gleam/uri | ||
import glow_auth.{Client} | ||
import glow_auth/access_token.{decode_token_from_response} | ||
import glow_auth/token_request.{RequestBody, ScopeString, client_credentials} | ||
import glow_auth/uri/uri_builder.{RelativePath} | ||
pub fn main() { | ||
// Replace the values for the let bindings with the values for your auth server | ||
// and client. | ||
let client_id = "<your client id>" | ||
let client_secret = "<your client secret>" | ||
let base_uri = "https://example.com" | ||
let token_endpoint = "token" | ||
let scope = "scope1 scope2[ ... scopeN]" | ||
// Use the values above to create and send a token request to the auth server. | ||
// 1. Create the site Uri to serve as the base path. | ||
use site <- result.then(uri.parse(base_uri)) | ||
// 2. Create a Client using the client_id, client_secret, and site. | ||
let client = Client(client_id, client_secret, site) | ||
// 3. Create a request by calling client_credentials with parameters: | ||
// a. The Client created in step (2). | ||
// b. The token path to be appended to the site Uri created in step (1). | ||
// c. The AuthScheme. (RequestBody or AuthHeader) | ||
// d. The Access Token Scope. (ScopeList, ScopeString, or DefaultScope) | ||
let request = | ||
client_credentials( | ||
client, | ||
RelativePath(token_endpoint), | ||
RequestBody, | ||
ScopeString(scope), | ||
) | ||
// 4. Send the token request to the auth server. | ||
let response = hackney.send(request) | ||
// 5. Decode the token from the response body when an Ok. | ||
// Handle a Error response according to your application's needs. | ||
let token = case response { | ||
Ok(wrapped) -> decode_token_from_response(wrapped.body) | ||
_ -> panic | ||
} | ||
// View the Result token in the console. | ||
io.debug(token) | ||
|> Ok | ||
} | ||
``` | ||
|
||
[cc1]: ./glow_auth/token_request#Scope |
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
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,72 @@ | ||
import gleam/http/request.{type Request} | ||
import gleam/list | ||
import gleam/result | ||
import gleam/string | ||
import gleam/uri | ||
import gleeunit/should | ||
import glow_auth.{Client} | ||
import glow_auth/token_request.{ | ||
type Scope, DefaultScope, RequestBody, ScopeList, ScopeString, | ||
client_credentials, | ||
} | ||
import glow_auth/uri/uri_builder | ||
|
||
fn make_request( | ||
scope: Scope, | ||
_handler: fn(Request(String)) -> Result(String, Nil), | ||
) -> Result(Request(String), Nil) { | ||
use example <- result.then(uri.parse("example.com")) | ||
let req = | ||
example | ||
|> Client("id", "secret", _) | ||
|> client_credentials(uri_builder.RelativePath("token"), RequestBody, scope) | ||
|
||
Ok(req) | ||
} | ||
|
||
/// Tests that a scope is added to the request body as a space-deliminated string | ||
/// of trimed scope values from a ScopeList. | ||
pub fn scope_list_test() { | ||
let scopes = [" first ", " second ", " third "] | ||
use req <- make_request(ScopeList(scopes)) | ||
req.body | ||
|> extract_scope | ||
|> test_scope("first second third") | ||
|
||
Ok("") | ||
} | ||
|
||
/// Tests that a scope is added to the request body as a trimmed string of one or | ||
/// more pre-joined, space-deliminated strings. | ||
pub fn scope_string_test() { | ||
let scopes = " third fourth fifth " | ||
use req <- make_request(ScopeString(scopes)) | ||
req.body | ||
|> extract_scope | ||
|> test_scope(string.trim(scopes)) | ||
|
||
Ok("") | ||
} | ||
|
||
/// Tests that the scope is not added to the request if it's a DefaultScope. | ||
pub fn default_scope_test() { | ||
use req <- make_request(DefaultScope) | ||
req.body | ||
|> extract_scope | ||
|> should.equal(Error(Nil)) | ||
|
||
Ok("") | ||
} | ||
|
||
fn extract_scope(body: String) -> Result(String, Nil) { | ||
body | ||
|> uri.percent_decode | ||
|> result.unwrap("") | ||
|> string.split("&") | ||
|> list.filter(fn(s) { string.starts_with(s, "scope") }) | ||
|> list.first | ||
} | ||
|
||
fn test_scope(actual: Result(String, Nil), expected: String) { | ||
actual |> should.equal(Ok("scope=" <> expected)) | ||
} |