2

I have a fully working connected app, and now I want to authorize only managed package licensed users. Let's assume the managed package namespace is xyz.

Scenario:

  • ISV A releases xyz
  • Company B has 100 salesforce users in its org
  • Company B buys and assigns 10 xyz licenses to 10 users
  • ISV A releases an external service and wants that only their licensed users can access it (for Company B only those 10 licensed users)

Question 1: What would be the best approach to the previous point?

Attempt 1

  1. Create a Connected App with OAuth to authorize the salesforce users
  2. Customize the behaviour with a custom ConnectedAppPlugin enter image description here
  3. ConnectedAppPlugin body:

    global class CustomConnectedAppPlugin extends Auth.ConnectedAppPlugin {
    
        global override boolean authorize(Id userId, Id connectedAppId, boolean isAdminApproved, Auth.InvocationContext context) {
            User user = [select Id, Username from User where Id = :userId];
            System.debug('User requesting authorization: ' + user.Username);
            boolean result = ![select Id from UserPackageLicense where PackageLicense.NamespacePrefix = 'xyz' and UserId = :userId].isEmpty();
            System.debug('Connected App Plugin authorized: ' + result);
            return result;
        }
    }
    

Considerations about attempt 1

  • I intentionally left the Run As field blank, because in the documentation I found this sentence:

    The class runs on behalf of the current user of the connected app. This user must have permission to use the connected app for the plug-in to work.

Attempt 1 result

The custom ConnectedAppPlugin code is never called.

Attempt 2

Same as Attempt 1, but specifying a sys admin in the Run As field

Considerations about attempt 2

In the documentation I found the following (not very helpful) explanation about the Run As field:

For Run As, select the name of the user to run the plugin as. The plug-in runs on behalf of a user account. If the user isn’t authorized for the connected app, use the authorize method to do so. For more information, see the ConnectedAppPlugin class in the Apex Code Developer's Guide.

Attempt 2 result

If I try to get the authorization logging in as a random user, the authorize method always receives (surprise) the userId of the Run As user, but at least the code in the custom ConnectedAppPlugin is executed.

Question 2: what am I missing?

2
  • According to the documentation the userId parameter is the 15-character ID of the user attempting to use the connected app. So it is strange that you are seeing the Id of the Run As user.
    – Folkert
    Jul 9, 2018 at 13:59
  • Hi Francesco, did you figure out the solution for this problem? Could you please share your solution if you have one?
    – Patlatus
    Sep 21, 2022 at 13:41

1 Answer 1

0

Well, the documentation you mentioned, reads:

authorize(userId, connectedAppId, isAdminApproved, context)
Authorizes the specified user to access the connected app. If the connected app is set for users to self-authorize, this method isn’t invoked.

Which means, if connected app is set for users to self-authorize, that method and ConnectedAppPlugin is never called or invoked and this is the reason why don't you see ConnectedAppPlugin called in attempt 1.

Attempt 2 bring an interesting point: either you have set users to preapprove by admin or such a setting keeps this option while installing the package (even though by default any preapprove settings are reset to users self-authorize)

Also, the documentation reads:

Depending on the methods used in your ConnectedAppPlugin Apex class, you can sometimes leave this field blank.
If your Apex class uses the authorize, modifySAMLResponse, or refresh methods, specify an execution user in the Run As field.

So I just checked it, the authorization works only when both admin has set preapproved users and a user for class is selected.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .