Hi everyone,

I have provided a first version, you can check it out here: https://github.com/apache/ofbiz-framework/pull/1790

Good news first:

Before any changes, the structure of apis as independant endpoints was mostly already present, if not leveraged for something like authentication based on the targeted api.

More specific:

On the current trunk, <api> enforce a non-optional path attribute, unique to that api. That in effect makes each <api> defined via rest.xml discoverable under a unique segment

 .../rest/<api-path-element>/<optional-other-path-segments/...

That attribute is used as a key when api definitions get stored in MICRO_APIs. The only necessary change to allow grouping apis was thus, to allow apis to define the same path on <api> level. I renamed the path element to "apiGroupPath" and provided the rest.xsd definition with additional description to make that relationship clear. I changed MICRO_API and related code from handling single ModelApis to working with lists (Map<String, ModelApi> to Map<String, List<ModelApi>>). I also added additional checks, to prevent apis of the same group from defining the same endpoints.

Note that until here, there is no functional change to how the rest-api works, its only organization so far.

Next i restructured existing apis and introduced "api" as the default api group for ofbiz-native apis. Currently in ofbiz framework we have the restExampleApi.rest.xml (renamed to testApi.rest.xml, since it provides only endpoints for testing), bom-management.rest.xml, production-runs.rest.xml, mrp-planning.rest.xml and rountg-cost.rest.xml.

I moved the path element previous defined at <api> level one resource element down and changed apiGroupPath to "api".  That means if an endpoints was previously available at:

/rest/bom-management/someService

It will now be available at

/rest/api/bom-management/someService

I implemented an authorization check based on the apiGroup. I added apiGroupPath as a Path-Parameter to the auth endpoint

/rest/auth/token -> /rest/auth/{apiGroupPath}/token

Prior to issuing the token, the SecurityGroup configured for the rest-api is retrieved. If the user tries getting a token for a api that has no securityGroup configured via via rest.api .properties, it will deny the token and return this information to the user. If credentials are valid and a token issued, the apiGroupPath ist then added to the claims of the token issued. Upon verification it now validates if this parameter matched the api the user calls after it verified that the token itself is genuine. Creating a refresh token retrieves the apiGroupPath and adds it to the new token automatically.

Regarding SwaggerUI:

Apis in swagger will now be filtered based on their apiGroup.

previously:

any call to /docs/ forwarded to /docs/swagger-ui.html

Now a filter intercepts all calls to the swagger webapp and checks wether an explicit apiGroupPath is provided,

Previously: /docs/apiGroupPath/swagger-ui.html

swagger-ui.html itself does a call to

rest/openapi.json

where the swaggerUI is constructed. This endpoint changed to

rest/{apiGroupPath}/openapi.json

to allow the passing of the group we want to filter for. If the user does not provide an apiGroupPath, swagger-ui.html sets it to the default "api" to display ofbiz standard endpoints. For backwards compatability, calling /docs/ also gets forwarded with the default.

To sum up the valid ways to reach swagger-ui:

/docs/ (displays apis for group "api" - backward-compatability)

/docs/swagger-ui.html (displays apis for group "api" - backward-compatability)

/docs/api/swagger-ui.html (displays apis for group "api" - default)

docs/<someApiGroup>/swagger-ui.html /displays apis for group <someApiGroup>)

(Note that endpoints exposed as a resource like rest/auth/{apiGroupPath}/token are independant of this filter and always included)

I did intentionally NOT gate the swaggerUi itself. While we could hook a simple login filter via web.xml, since wagger-ui.html internally does a call to /rest/{apiGroupPath}/openapi.json the only way to secure it truly would be to hide the endpoint behind authorization, which means we would need to create an auth token for visiting swaggerUI itself. That does not seem reasonable to me at this point.

Happy the receive your feedback, but note that I will be gone a few days, will respond once im back.

Best regards,

Lukas

Reply via email to