Skip to content

Commit

Permalink
working user openid4vp on retrieving transfer request
Browse files Browse the repository at this point in the history
  • Loading branch information
woutslakhorst committed May 22, 2024
1 parent 3fdeb77 commit 2ad0bc7
Show file tree
Hide file tree
Showing 17 changed files with 213 additions and 33 deletions.
3 changes: 0 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ gen-api:

oapi-codegen -generate types -package types -exclude-schemas SharedCarePlan -o domain/types/generated_types.go api/api.yaml
oapi-codegen -generate server -package api -o api/generated.go api/api.yaml
oapi-codegen -generate client,types -package auth \
-import-mapping='../common/ssi_types.yaml:github.com/nuts-foundation/nuts-demo-ehr/nuts/client/common' \
-o nuts/client/auth/generated.go https://nuts-node.readthedocs.io/en/latest/_static/auth/v1.yaml
oapi-codegen -generate client,types -package common -exclude-schemas VerifiableCredential,VerifiablePresentation,DID,DIDDocument -generate types,skip-prune -o nuts/client/common/generated.go https://nuts-node.readthedocs.io/en/latest/_static/common/ssi_types.yaml
oapi-codegen -generate client,types -package discovery \
-import-mapping='../common/ssi_types.yaml:github.com/nuts-foundation/nuts-demo-ehr/nuts/client/common' \
Expand Down
4 changes: 2 additions & 2 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func (w Wrapper) AuthenticateWithPassword(ctx echo.Context) error {
return ctx.JSON(200, types.SessionToken{Token: string(token)})
}

func (w Wrapper) CreateAuthorizationRequest(ctx echo.Context) error {
func (w Wrapper) CreateAuthorizationRequest(ctx echo.Context, params CreateAuthorizationRequestParams) error {
customerID, err := w.APIAuth.GetCustomerIDFromHeader(ctx)
if err != nil {
return err
Expand All @@ -118,7 +118,7 @@ func (w Wrapper) CreateAuthorizationRequest(ctx echo.Context) error {
if err != nil {
return ctx.JSON(http.StatusInternalServerError, errorResponse{err})
}
response, err := w.NutsClient.CreateAuthenticationRequest(*customer.Did)
response, err := w.NutsClient.CreateAuthenticationRequest(*customer.Did, params.Verifier, params.Scope, params.RedirectUri)
if err != nil {
return err
}
Expand Down
25 changes: 25 additions & 0 deletions api/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,25 @@ paths:
post:
description: Create an OAuth2 authorize request. It returns a redirectURL.
operationId: createAuthorizationRequest
parameters:
- name: verifier
in: query
description: The DID of the verifier
required: true
schema:
type: string
- name: scope
in: query
description: The oauth scope
required: true
schema:
type: string
- name: redirect_uri
in: query
description: The URL to redirect the user to after the authorization.
required: true
schema:
type: string
responses:
'200':
description: Request created.
Expand Down Expand Up @@ -494,6 +513,12 @@ paths:
required: true
schema:
type: string
- name: token
in: query
description: The access token
required: true
schema:
type: string
get:
operationId: getTransferRequest
description: Get the details of a transfer request sent by another care organization.
Expand Down
3 changes: 3 additions & 0 deletions api/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/hex"
"errors"
"fmt"
"github.com/nuts-foundation/nuts-demo-ehr/domain/types"
"github.com/nuts-foundation/nuts-demo-ehr/nuts/client/iam"
"net/http"
"strings"
Expand Down Expand Up @@ -63,6 +64,8 @@ type JWTStandardClaims struct {
Subject string `json:"sub,omitempty"`
}

type CreateAuthorizationRequestParams types.CreateAuthorizationRequestParams

func NewAuth(key *ecdsa.PrivateKey, customers customers.Repository, passwd string) *Auth {
result := &Auth{
sessionKey: key,
Expand Down
53 changes: 47 additions & 6 deletions api/generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion api/inbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ import (
"github.com/labstack/echo/v4"
)

type GetTransferRequestParams types.GetTransferRequestParams
type ChangeTransferRequestStateParams types.ChangeTransferRequestStateParams

// GetTransferRequest handles requests to receive a transfer request.
func (w Wrapper) GetTransferRequest(ctx echo.Context, requestorDID string, fhirTaskID string) error {
func (w Wrapper) GetTransferRequest(ctx echo.Context, requestorDID string, fhirTaskID string, params GetTransferRequestParams) error {
session, err := w.getSession(ctx)
if err != nil {
return err
Expand All @@ -22,6 +25,7 @@ func (w Wrapper) GetTransferRequest(ctx echo.Context, requestorDID string, fhirT
session.CustomerID,
requestorDID,
fhirTaskID,
params.Token,
)
if err != nil {
return fmt.Errorf("unable to get transferRequest: %w", err)
Expand Down
2 changes: 1 addition & 1 deletion api/transfer.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func (w Wrapper) GetTransfer(ctx echo.Context, transferID string) error {
return ctx.JSON(http.StatusOK, transfer)
}

func (w Wrapper) ChangeTransferRequestState(ctx echo.Context, requesterDID string, fhirTaskID string) error {
func (w Wrapper) ChangeTransferRequestState(ctx echo.Context, requesterDID string, fhirTaskID string, params ChangeTransferRequestStateParams) error {
updateRequest := &types.TransferNegotiationStatus{}
err := ctx.Bind(updateRequest)
if err != nil {
Expand Down
7 changes: 6 additions & 1 deletion docker-compose/left/config/pep/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,15 @@ http {
}

location /fhir {
auth_request /_oauth2_delegated;
auth_request_set $auth_status $upstream_status;
auth_request_set $xuserinfo $sent_http_x_userinfo;

proxy_set_header X-Userinfo $xuserinfo;
proxy_pass http://hapi-left:8080;
}

location /web/external {
location /web/external/transfer/notify {
auth_request /_oauth2_delegated;
auth_request_set $auth_status $upstream_status;
auth_request_set $xuserinfo $sent_http_x_userinfo;
Expand Down
Binary file modified docker-compose/left/data/node/sqlite.db
Binary file not shown.
7 changes: 6 additions & 1 deletion docker-compose/right/config/pep/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,15 @@ http {
}

location /fhir {
auth_request /_oauth2_delegated;
auth_request_set $auth_status $upstream_status;
auth_request_set $xuserinfo $sent_http_x_userinfo;

proxy_set_header X-Userinfo $xuserinfo;
proxy_pass http://hapi-right:8080;
}

location /web/external {
location /web/external/transfer/notify {
auth_request /_oauth2_delegated;
auth_request_set $auth_status $upstream_status;
auth_request_set $xuserinfo $sent_http_x_userinfo;
Expand Down
Binary file modified docker-compose/right/data/node/sqlite.db
Binary file not shown.
23 changes: 16 additions & 7 deletions domain/transfer/receiver/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type TransferService interface {
// CreateOrUpdate creates or updates an incoming transfer record in the local storage
CreateOrUpdate(ctx context.Context, status string, customerID int, senderDID, fhirTaskID string) error
UpdateTransferRequestState(ctx context.Context, customerID int, requesterDID, fhirTaskID string, newState string) error
GetTransferRequest(ctx context.Context, customerID int, requesterDID string, fhirTaskID string) (*types.TransferRequest, error)
GetTransferRequest(ctx context.Context, customerID int, requesterDID string, fhirTaskID string, token string) (*types.TransferRequest, error)
}

type service struct {
Expand Down Expand Up @@ -52,7 +52,7 @@ func (s service) UpdateTransferRequestState(ctx context.Context, customerID int,
return err
}

fhirClient, err := s.getRemoteFHIRClient(ctx, requesterDID, *customer.Did)
fhirClient, err := s.getServiceFHIRClient(ctx, requesterDID, *customer.Did)
if err != nil {
return err
}
Expand Down Expand Up @@ -85,7 +85,7 @@ func (s service) UpdateTransferRequestState(ctx context.Context, customerID int,
return fmt.Errorf("invalid state change from %s to %s", task.Status, newState)
}

func (s service) GetTransferRequest(ctx context.Context, customerID int, requesterDID string, fhirTaskID string) (*types.TransferRequest, error) {
func (s service) GetTransferRequest(ctx context.Context, customerID int, requesterDID string, fhirTaskID string, accessToken string) (*types.TransferRequest, error) {
const getTransferRequestErr = "unable to get transferRequest: %w"

customer, err := s.customerRepo.FindByID(customerID)
Expand All @@ -94,7 +94,7 @@ func (s service) GetTransferRequest(ctx context.Context, customerID int, request
}

// First get the task, this uses a separate task auth credential
fhirTaskClient, err := s.getRemoteFHIRClient(ctx, requesterDID, *customer.Did)
fhirTaskClient, err := s.getUserFHIRClient(ctx, requesterDID, *customer.Did, accessToken)
if err != nil {
return nil, err
}
Expand All @@ -119,7 +119,7 @@ func (s service) GetTransferRequest(ctx context.Context, customerID int, request
}

if task.AdvanceNoticeID != nil {
fhirCompositionClient, err := s.getRemoteFHIRClient(ctx, requesterDID, *customer.Did)
fhirCompositionClient, err := s.getServiceFHIRClient(ctx, requesterDID, *customer.Did)
if err != nil {
return nil, err
}
Expand All @@ -138,7 +138,7 @@ func (s service) GetTransferRequest(ctx context.Context, customerID int, request

// If the task input contains the nursing handoff
if task.NursingHandoffID != nil {
fhirCompositionClient, err := s.getRemoteFHIRClient(ctx, requesterDID, *customer.Did)
fhirCompositionClient, err := s.getServiceFHIRClient(ctx, requesterDID, *customer.Did)
if err != nil {
return nil, err
}
Expand All @@ -157,7 +157,7 @@ func (s service) GetTransferRequest(ctx context.Context, customerID int, request
return &transferRequest, nil
}

func (s service) getRemoteFHIRClient(ctx context.Context, authorizerDID string, localRequesterDID string) (fhir.Client, error) {
func (s service) getServiceFHIRClient(ctx context.Context, authorizerDID string, localRequesterDID string) (fhir.Client, error) {
fhirServer, err := s.registry.GetCompoundServiceEndpoint(ctx, authorizerDID, transfer.SenderServiceName, "fhir")
if err != nil {
return nil, fmt.Errorf("error while looking up authorizer's FHIR server (did=%s): %w", authorizerDID, err)
Expand All @@ -171,3 +171,12 @@ func (s service) getRemoteFHIRClient(ctx context.Context, authorizerDID string,
}
return fhir.NewFactory(fhir.WithURL(fhirServer), fhir.WithAuthToken(accessToken))(), nil
}

func (s service) getUserFHIRClient(ctx context.Context, authorizerDID string, localRequesterDID string, accessToken string) (fhir.Client, error) {
fhirServer, err := s.registry.GetCompoundServiceEndpoint(ctx, authorizerDID, transfer.SenderServiceName, "fhir")
if err != nil {
return nil, fmt.Errorf("error while looking up authorizer's FHIR server (did=%s): %w", authorizerDID, err)
}

return fhir.NewFactory(fhir.WithURL(fhirServer), fhir.WithAuthToken(accessToken))(), nil
}
24 changes: 24 additions & 0 deletions domain/types/generated_types.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 7 additions & 6 deletions nuts/client/iam.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,27 @@ import (
)

type Iam interface {
CreateAuthenticationRequest(customerDID string) (*nutsIamClient.RedirectResponseWithID, error)
CreateAuthenticationRequest(customerDID string, verifierDID string, scope string, redirectUri string) (*nutsIamClient.RedirectResponseWithID, error)
GetAuthenticationResult(token string) (*nutsIamClient.TokenResponse, error)
IntrospectAccessToken(ctx context.Context, accessToken string) (*nutsIamClient.TokenIntrospectionResponse, error)
}

var _ Iam = HTTPClient{}

func (c HTTPClient) CreateAuthenticationRequest(customerDID string) (*nutsIamClient.RedirectResponseWithID, error) {
func (c HTTPClient) CreateAuthenticationRequest(customerDID string, verifierDID string, scope string, redirectUri string) (*nutsIamClient.RedirectResponseWithID, error) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

tokenType := nutsIamClient.UserAccessTokenRequestTokenTypeBearer
resp, err := c.iam().RequestUserAccessToken(ctx, customerDID, nutsIamClient.RequestUserAccessTokenJSONRequestBody{
RedirectUri: "http://localhost:1304/#/close",
Scope: "test",
RedirectUri: redirectUri,
Scope: scope,
PreauthorizedUser: &nutsIamClient.UserDetails{
Id: "12345",
Name: "John Doe",
Role: "Verpleegkundige niveau 4",
},
Verifier: customerDID,
TokenType: &tokenType,
Verifier: verifierDID,
})

if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion web/src/Close.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default {
mounted() {
// close window after 2 seconds
window.opener = self;
setTimeout(window.close, 2000)
setTimeout(window.close, 20)
}
}
</script>
Loading

0 comments on commit 2ad0bc7

Please sign in to comment.