+4
Makefile
+4
Makefile
+230
README.md
+230
README.md
···+> You should always validate user input. The example/test code inside this repo may be used as an implementation guide, but no guarantees are made.+If you do not already have a private JWK for your application, first create one. There is a helper CLI tool that can generate one for you. From the project directory, run+You will need to read the JWK from your application and parse it using `oauth.ParseJWKFromBytes`.+The client metadata will need to be accessible from your domain. An example using `echo` is below.+You will also need to serve your private JWK's __public key__ from your domain. Again, an example is below.+There are examples of the authentication flow inside of `cmd/client_tester/handle_auth.go`, however we'll talk about some general points here.+You should allow for users to input their handle, DID, or PDS URL when detemrining where to send the user for authentication. An example that covers all the bases of what you'll need to do is when a user uses their handle.+By this point, you will have the necessary information to direct the user where they need to go.+You'll need to create a private DPoP JWK for the user before directing them to their PDS to authenticate. You'll need to store this in a later step, and you will need to pass it along inside the PAR request, so go ahead and marshal it as well.+// Note: the login hint - here `handle` - should only be set if you have a DID or handle. Leave it empty if all you+parResp, err := cli.SendParAuthRequest(ctx, authserver, authmeta, handle, scope, dpopPrivateKey)+It is up to you how you want to store these values. Most likely, you will want to store them in a database. You may also want to store the `state` variable in the user's session _as well as the database_ so you can verify it later. There's a basic implementation inside of `cmd/client_tester/handle_auth.go`.+Once you've stored the needed info, send the user to their PDS. The URL to redirect the user to should have both the `client_id` and `request_uri` `GET` parameters set.+u.RawQuery = fmt.Sprintf("client_id=%s&requires_uri=%s", url.QueryEscape(yourClientId), parResp.RequestUri)+Handling the response is pretty easy, though you'll want to check a few things once you receive the response.+You'll next need to load all of the request information you previously stored. Once you have that information, you can perform the initial token request.+itResp, err := cli.InitialTokenRequest(ctx, resCode, resIss, requestInfo.PkceVerifier, requestInfo.DpopAuthserverNonce, requestInfo.privateJwk)+Finally, check that the scope received matches the requested scope. Also, if you didn't have the user's DID before redirecting earlier, you can now get their DID from `itResp.Sub`.+Now, you can store the response items to make make authenticated requests later. You likely will want to store at least the user's DID in a secure session so that you know who the user is.
+10
-16
cmd/client_test/handle_auth.go
+10
-16
cmd/client_test/handle_auth.go
·········+parResp, err := s.oauthClient.SendParAuthRequest(ctx, authserver, meta, loginHint, scope, dpopPrivateKey)···+u.RawQuery = fmt.Sprintf("client_id=%s&request_uri=%s", url.QueryEscape(serverMetadataUrl), parResp.RequestUri)···
+1
-2
cmd/client_test/main.go
+1
-2
cmd/client_test/main.go
······
+2
-2
cmd/client_test/user.go
+2
-2
cmd/client_test/user.go
······
+1
-1
generic.go
+1
-1
generic.go
+37
-28
oauth.go
+37
-28
oauth.go
·········+return nil, fmt.Errorf("received error from server when submitting par request: %s", rmap["error"])+return nil, fmt.Errorf("received error from server when submitting par request: %s", rmap["error"])···
+5
-5
oauth_test.go
+5
-5
oauth_test.go
············