Repository: Nerzal/gocloak
Pull request #270 (2021-04-02 11:14:46)

Adding requesting party permission decision method


Patch:
diff --git a/README.md b/README.md
index 6c8b0a1..d8b0c9b 100644
--- a/README.md
+++ b/README.md
@@ -156,7 +156,8 @@ type GoCloak interface {
 	GetToken(ctx context.Context, realm string, options TokenOptions) (*JWT, error)
 	GetRequestingPartyToken(ctx context.Context, token, realm string, options RequestingPartyTokenOptions) (*JWT, error)
 	GetRequestingPartyPermissions(ctx context.Context, token, realm string, options RequestingPartyTokenOptions) (*[]RequestingPartyPermission, error)
-
+	GetRequestingPartyPermissionDecision(ctx context.Context, token, realm string, options RequestingPartyTokenOptions) (*RequestingPartyPermissionDecision, error)
+	
 	Login(ctx context.Context, clientID, clientSecret, realm, username, password string) (*JWT, error)
 	LoginOtp(ctx context.Context, clientID, clientSecret, realm, username, password, totp string) (*JWT, error)
 	Logout(ctx context.Context, clientID, clientSecret, realm, refreshToken string) error
diff --git a/client.go b/client.go
index 25b6b28..a1e4cf6 100644
--- a/client.go
+++ b/client.go
@@ -458,6 +458,23 @@ func (client *gocloak) GetRequestingPartyPermissions(ctx context.Context, token,
 	return &res, nil
 }
 
+// GetRequestingPartyPermissionDecision returns a requesting party permission decision granted by the server
+func (client *gocloak) GetRequestingPartyPermissionDecision(ctx context.Context, token, realm string, options RequestingPartyTokenOptions) (*RequestingPartyPermissionDecision, error) {
+	const errMessage = "could not get requesting party token"
+
+	var res RequestingPartyPermissionDecision
+
+	options.ResponseMode = StringP("decision")
+
+	resp, err := client.getRequestingParty(ctx, token, realm, options, &res)
+
+	if err := checkForError(resp, err, errMessage); err != nil {
+		return nil, err
+	}
+
+	return &res, nil
+}
+
 // RefreshToken refreshes the given token.
 // May return a *APIError with further details about the issue.
 func (client *gocloak) RefreshToken(ctx context.Context, refreshToken, clientID, clientSecret, realm string) (*JWT, error) {
diff --git a/gocloak.go b/gocloak.go
index 71b2442..8c0ce49 100644
--- a/gocloak.go
+++ b/gocloak.go
@@ -20,6 +20,8 @@ type GoCloak interface {
 	GetRequestingPartyToken(ctx context.Context, token, realm string, options RequestingPartyTokenOptions) (*JWT, error)
 	// GetRequestingPartyPermissions returns a permissions granted by the server to requesting party
 	GetRequestingPartyPermissions(ctx context.Context, token, realm string, options RequestingPartyTokenOptions) (*[]RequestingPartyPermission, error)
+	// GetRequestingPartyPermissionDecision returns a permission decision granted by the server to requesting party
+	GetRequestingPartyPermissionDecision(ctx context.Context, token, realm string, options RequestingPartyTokenOptions) (*RequestingPartyPermissionDecision, error)
 	// Login sends a request to the token endpoint using user and client credentials
 	Login(ctx context.Context, clientID, clientSecret, realm, username, password string) (*JWT, error)
 	// LoginOtp performs a login with user credentials and otp token
diff --git a/models.go b/models.go
index 5991669..0fd2f67 100644
--- a/models.go
+++ b/models.go
@@ -828,6 +828,11 @@ type RequestingPartyPermission struct {
 	Scopes       *[]string          `json:"scopes,omitempty"`
 }
 
+// RequestingPartyPermissionDecision is returned by request party token with response type set to "decision"
+type RequestingPartyPermissionDecision struct {
+	Result *bool `json:"result,omitempty"`
+}
+
 // UserSessionRepresentation represents a list of user's sessions
 type UserSessionRepresentation struct {
 	Clients    *map[string]string `json:"clients,omitempty"`


Test patch:
diff --git a/client_test.go b/client_test.go
index 0cd26de..3e0d159 100644
--- a/client_test.go
+++ b/client_test.go
@@ -645,7 +645,7 @@ func TestGocloak_GetRawUserInfo(t *testing.T) {
 	require.NotEmpty(t, userInfo)
 }
 
-func TestGocloak_RequestPermission(t *testing.T) {
+func TestGocloak_RetrospectRequestingPartyToken(t *testing.T) {
 	t.Parallel()
 	cfg := GetConfig(t)
 	client := NewClientWithDebug(t)
@@ -701,6 +701,90 @@ func TestGocloak_RequestPermission(t *testing.T) {
 	require.Equal(t, "Default Resource", *permissions[0].RSName, "GetRequestingPartyToken failed")
 }
 
+func TestGocloak_GetRequestingPartyPermissions(t *testing.T) {
+	t.Parallel()
+	cfg := GetConfig(t)
+	client := NewClientWithDebug(t)
+	SetUpTestUser(t, client)
+	token, err := client.Login(
+		context.Background(),
+		cfg.GoCloak.ClientID,
+		cfg.GoCloak.ClientSecret,
+		cfg.GoCloak.Realm,
+		cfg.GoCloak.UserName,
+		cfg.GoCloak.Password)
+	require.NoError(t, err, "login failed")
+
+	rpp, err := client.GetRequestingPartyPermissions(
+		context.Background(),
+		token.AccessToken,
+		"",
+		gocloak.RequestingPartyTokenOptions{
+			Audience: gocloak.StringP(cfg.GoCloak.ClientID),
+			Permissions: &[]string{
+				"Default Resource",
+			},
+		})
+	require.Error(t, err, "GetRequestingPartyPermissions failed")
+	require.Nil(t, rpp)
+
+	rpp, err = client.GetRequestingPartyPermissions(
+		context.Background(),
+		token.AccessToken,
+		cfg.GoCloak.Realm,
+		gocloak.RequestingPartyTokenOptions{
+			Audience: gocloak.StringP(cfg.GoCloak.ClientID),
+			Permissions: &[]string{
+				"Default Resource",
+			},
+		})
+	require.NoError(t, err, "GetRequestingPartyPermissions failed")
+	require.NotNil(t, rpp)
+
+	t.Log(rpp)
+	permissions := *rpp
+	require.Len(t, permissions, 1, "GetRequestingPartyPermissions failed")
+	require.Equal(t, "Default Resource", *permissions[0].ResourceName, "GetRequestingPartyPermissions failed")
+}
+
+func TestGocloak_GetRequestingPartyPermissionDecision(t *testing.T) {
+	t.Parallel()
+	cfg := GetConfig(t)
+	client := NewClientWithDebug(t)
+	SetUpTestUser(t, client)
+	token, err := client.Login(
+		context.Background(),
+		cfg.GoCloak.ClientID,
+		cfg.GoCloak.ClientSecret,
+		cfg.GoCloak.Realm,
+		cfg.GoCloak.UserName,
+		cfg.GoCloak.Password)
+	require.NoError(t, err, "login failed")
+
+	dec, err := client.GetRequestingPartyPermissionDecision(
+		context.Background(),
+		token.AccessToken,
+		"",
+		gocloak.RequestingPartyTokenOptions{
+			Audience: gocloak.StringP(cfg.GoCloak.ClientID),
+		})
+	require.Error(t, err, "GetRequestingPartyPermissions failed")
+	require.Nil(t, dec)
+
+	dec, err = client.GetRequestingPartyPermissionDecision(
+		context.Background(),
+		token.AccessToken,
+		cfg.GoCloak.Realm,
+		gocloak.RequestingPartyTokenOptions{
+			Audience: gocloak.StringP(cfg.GoCloak.ClientID),
+		})
+	require.NoError(t, err, "GetRequestingPartyPermissions failed")
+	require.NotNil(t, dec)
+
+	t.Log(dec)
+	require.True(t, *dec.Result)
+}
+
 func TestGocloak_GetCerts(t *testing.T) {
 	t.Parallel()
 	cfg := GetConfig(t)