Artifact Authorization Failed Error (How to Solve)

I have a problem that I’ve faced before, but I’d like to make a post that is searchable so that people can fix it for themselves in the future. I’m not sure how to fix it now, but we’re going to go through the thought process of how to solve this problem and problems like this in Moqui.

Context:

I’m calling a service in UserServices.xml called set#Preference (reference).

    <service verb="set" noun="Preference" allow-remote="true">
        <in-parameters>
            <parameter name="preferenceKey" required="true"/>
            <parameter name="preferenceValue"/>
        </in-parameters>
        <actions><script>ec.user.setPreference(preferenceKey, preferenceValue)</script></actions>
    </service>

In this example the service is called in the pre-actions block of a screen. The context for the call doesn’t really matter, so I simplified it a bit.

    <pre-actions>
<!-- Pre logic -->
            <service-call name="org.moqui.impl.UserServices.set#Preference" in-map="[preferenceKey:'ACTIVE_ORGANIZATION',preferenceValue:organizationList.getFirst().toPartyId]"/>
<!-- Post logic -->
    </pre-actions>

After calling this service, I’m getting the error message:

10:35:41.969  WARN 18519094-156 .moqui.i.c.ArtifactExecutionFacadeImpl Artifact authorization failed: User *** is not authorized for All on Service org.moqui.impl.UserServices.set#Preference
Current artifact info: [name:'org.moqui.impl.UserServices.set#Preference', type:'AT_SERVICE', action:'AUTHZA_ALL', required: true, granted:false, user:'null', authz:'null', authAction:'null', inheritable:false, runningTime:0', txId:null]
Current artifact stack:
[name:'component://webroot/screen/webroot.xml/menuData', type:'AT_XML_SCREEN_TRANS', action:'AUTHZA_VIEW', required: false, granted:false, user:'***', authz:'AUTHZT_ALLOW', authAction:'AUTHZA_VIEW', inheritable:true, runningTime:0', txId:412]
[name:'component://webroot/screen/webroot.xml', type:'AT_XML_SCREEN', action:'AUTHZA_VIEW', required: false, granted:false, user:'null', authz:'null', authAction:'null', inheritable:false, runningTime:0', txId:412]
10:35:41.970 ERROR 18519094-156                  o.moqui.i.a.XmlAction Error running groovy script (org.moqui.context.ArtifactAuthorizationException: User *** is not authorized for All on Service org.moqui.impl.UserServices.set#Preference): 
1 : import static org.moqui.util.ObjectUtilities.*
2 : import static org.moqui.util.CollectionUtilities.*
3 : import static org.moqui.util.StringUtilities.*
4 : import java.sql.Timestamp
5 : import java.sql.Time
6 : import java.time.*
7 : // these are in the context by default: ExecutionContext ec, Map<String, Object> context, 
// Pre logic
13 :     if (true) {
14 :         ec.service.sync().name("org.moqui.impl.UserServices.set#Preference")
15 :             .parameters([preferenceKey:'ACTIVE_ORGANIZATION',preferenceValue:organizationList.getFirst().toPartyId]).call()
16 :         
17 :         if (ec.message.hasError()) return
18 :     }
// Post logic
24 : 
25 : // make sure the last statement is not considered the return value
26 : return;

How I interpret this is that in Moqui’s Artifact Authorization functionality (see docs), each service, screen, and more have an authorization to actually use. The Artifact Authorization functionality is typically based on an Artifact Group and applies to sub artifacts (like in a top level screen with inherit authz will apply to the sub screens to make it easier to manage). The user that is currently logged in only has explicit access to a custom app with basic very authorizations:

    <!-- Artifact group and authz for a Custom App -->
    <artifactGroups artifactGroupId="CUSTOM_APP" description="Custom App (via root screen)">
        <artifacts artifactName="component://customApp/screen/rootScreen.xml" artifactTypeEnumId="AT_XML_SCREEN" inheritAuthz="Y"/>
        <authz artifactAuthzId="CUSTOM_APP_USERS" userGroupId="CUSTOM_APP_USERS" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL">
            <filters entityFilterSetId="CUSTOM_APP_FILTER"/></authz>
    </artifactGroups>

Now the question is why are the authz not allowed for this user, or how to add the authz? I did a bit of searching and found that each Artifact Group has many Artifact Group Members. The Artifact Group Members can be a Entity, Other, REST API Path, Screen, Screen Content, Screen Transition, or Service. This means that just about anything can be filtered through the authz filter so that only certain people can access the artifact / resource. That’s awesome, and is so nice that it already exists.

So what we can do now, is add the artifact to the artifact group, and see if it lets us access the service now. I added the following to the data, and loaded it in the database:

        <artifacts artifactName="org.moqui.impl.UserServices.set#Preference" artifactTypeEnumId="AT_SERVICE" inheritAuthz="N" nameIsPattern="N"/>

And then, I didn’t get an authz error when going to that page anymore!

Summary:

When doing stuff in Moqui, it’s important and very helpful to have a bit of knowledge about the general structure of it. Then with that knowledge additional information can be searched or found quite easily. To do this, I suggest reading the framework docs, as this is where a lot of this general information is.

Hopefully this was interesting or helpful to people.

1 Like

Thanks for sharing!

1 Like