[OAuth2 Provider] Congrats for this job. I want to collaborate on the evolution!

Forge Component
(1)
Published on 23 Apr by leonardo.fernandes
1 vote
Published on 23 Apr by leonardo.fernandes

First of all, congrats for this work.


I'm a solutions architect and I'm involved for a long time with authentication/authorization solutions on my company.

This time we was building some apps on Outsystems and bring together our internal company solutions to Outsystems and authentication is again on focus.


I used our solution as a start point to our needs and as all clones, it's a little hard to observe what new things happen on original apps at forge.


I'll try to resume some things I made and hope you are interested in take a look and work together to evaluate some features.


Set the app to multi tenant and made some changes on this

Implemented password credential OAuth flow;


Translated the app to pt-br

Create a default config to define en-us as default language and changed this value on our environments;
Create a session start handler to change language;


Created timers to cleanup expired authorization codes and access tokens as in our enviroment the trafic on this will be some hard;


Created api to manage OAuth clients for external platform apps(just our internal);

Created api with for OAuth token endpoint to support other flows;

We have some scenarios where our 1st generation ERP talks to our 2nd generation ERP and in other we have modules on Outsystems talking to both...


I change the default implementations of client credentials to use a default user on token generated to guarantee that any flow where two apps on a trust relationship can execute any code dependent of user context.

To accomplish this I made some changes to OAuth client edit screen and detail screen.

The logic I used was to create a default user on all tenants and use this in absence of user selection on each client to use a default user;

On this screens I give the user the option to select other user to be used with the OAuth client on a client credentials flow;


I used your OnAuthorization action on default OnBeginWebRequest handler in our enterprise app template to make it available to new web apps and the orientation to use it on custom api authentication handler.

I create parameters to make this and other behaviors optional to not break your initial idea;

One thing I made is to allow switching authentication contexts from OAuth to normal cookies allowing very integrated internal enterprise apps to init an OAuth flow and end switching context passing an access token on url via tls to an Outsystem app;


There some other minor changes I can sent you to discussion;


Some challenges I see:

In our clone we made some changes that I think it will need stay as clone, but more close to your version and we can observe both and apply any fix;

I used our enterprise theme(Outsystems UI too) to maintain an enterprise look;

We use an clone of original OS user provider as the default lacks some features we need;


I think this cannot be resolve without having the clone, but if it was much more like yours we can stay updated(manually)

As all your solution was on a presentation module we end up with circular refs that we don't want;

As a test I separated all the core features on a new module, and it is very important to us to not have circular refs.


Hope you can add me to the team and we can collaborate a bit!


Márcio.



Fantastic work Márcio.

I will gladly add you to the team.

I am a true believer in the open source movement, so feel free to advance the component in any direction you see fit, the only thing I ask is for you to consider as much as possible an abstract usage, meaning try to keep dependencies and context to other code as low as possible, which you seem to follow anyway. However when in doubt it is always preferable to extend to a new feature than not doing it at all.

If a potential user doesn't want something they can always remove it or use a previous version.

Much appreciated

I'm very glad to hear from you that we will work together on this great solution!

I have submitted the request to join then team!

Later I will propose to divide the changes and elaborate some strategies to be more understandable to team and the final users.

Regards,
Márcio

Hi Márcio. It looks like you did a really good job!

A few notes that come to mind.

  1. It should be possible (and preferrably easy) to integrate the credentials management into a custom application. That's the reason why some of the data model and actions are public. This is how I envision custom use cases (such as pt-br translation that you mention) to be supported. You can build your own backoffice, and then you translate it. All your challenges would be solved by such an approach.
  2. Multi-tenant: looks promising! That was on my short-term plans.
  3. Password credential OAuth flow: great!
  4. Timers to cleanup expired authorization codes: also great! We'll also need to clean up access tokens.
  5. Client credentials to use a default: this was also in my short-term plans. This needs to be integrated with multi-tenant, and that's why I delayed it for later.
  6. Client credentials to use a default user: are you trying to enforce that client credentials will result in a user being logged in? If that's the case, then I disagree - client credentials could be used for machine-to-machine communication, which doesn't need a User Id. We'll need to talk for me to understand this specific requirement of yours.
  7. OnAuthorization action on default OnBeginWebRequest handler: that's not how I imagined it being used! But if it works, then great :)
  8. Allow switching authentication contexts from OAuth to normal cookies: I didn't understand this part. We'll need to talk.

Hi Leonardo,

Glad to see we agreed with almost all changes. I'll try to elaborate a bit on these we don't initially disagreed.


  1. Timers to cleanup expired authorization codes: also great! We'll also need to clean up access tokens.
    • Yes I implemented both.
  2. Client credentials to use a default: this was also in my short-term plans. This needs to be integrated with multi-tenant, and that's why I delayed it for later.
  3. Client credentials to use a default user: are you trying to enforce that client credentials will result in a user being logged in? If that's the case, then I disagree - client credentials could be used for machine-to-machine communication, which doesn't need a User Id. We'll need to talk for me to understand this specific requirement of yours.
    • Elaborating a bit more. In our enterprise expirience some apps use the user context to store things like language, timezone, and some apps framework use the authentication context to extract these iformation making then mandatory to some app features, and when two trusted apps are working togegher by client credentials some bussiness flow will fail on extract this information it already enforce to all their users. As i don't know what flows other apps will be using on the integration we feel this was needed to garantee that this context information was present all the time. The same was true about permissions been checked on a flow started by a integration via client credentials. Without user context we don't know about the user permissions and the execution of flow was compromised to fail.
    • I think this can be by configuration and turned off by default to not impact who was not inrested in this feature.
    • The support to a user involved in client credentials ou other flow to be effectively loged in depends of configuration too. I give support for this only on web transfer of authentication context, when an user pre-authenticated via OAuth made a request to a web app that has a handler where the OnAuthentication action was configured to allow context switch.
    • Since I turned the app multi tenant I had to create a default user to each tenant via timer, same time I'm giving the user a chance to choose if he want to use another user. I we never know what level of permissions this user need to have. and the today permissions may be insuficient tomorow on new features and the integration will be incomplete.
  4. OnAuthorization action on default OnBeginWebRequest handler: that's not how I imagined it being used! But if it works, then great :)
    • It works now and was the minor point of contact I saw when implemented this feature, but always we can discute it a bit more as the changes are being made.
  5. Allow switching authentication contexts from OAuth to normal cookies: I didn't understand this part. We'll need to talk.
    • I elaborated a bit on answer 3.

Feel free to question everything you think we can elaborate more!



About your requirement of having a default user (due to a requirement from your app framework).

You could accomplish it by checking if there's a user logged in, after the OnAuthentication. If there isn't, then you invoke the Login action for your default user. This way you keep this specific requirement out of the core component.

What do you think?

Yes, the line is almost this.

This time I just included the userid of the default user created on tenant or if the user choose other default user for that OAuth client i use that.

By default on OAuth flows I didn't make any changes to a normal user authenticated via normal cookies. I dont't want so support a client creentials authenticated user to init an authentication context change. Only flows that involve a real user could switch from OAuth to regular web authentication via cookies.

When we get this part of changes I send you the app to you revise and we make the fine adjustments.

For now i just want to upload a new version with the two modules separated.

After that I plan to split the changes in minor ones to allow us revise the changes.

Thank you for your asap responses.

I wouldn't split the application... do you see any advantage in that?

You can have a single module with a default backoffice that will serve most use cases, and entities/actions made public for the people that need to extend it. This makes it easier to debug and easier to evolve the component.

Don't get me wrong, I don't want to stop you publishing that version. But I would like to understand what we would gain from it.

Sure,

I split it on our clone because we changed the base theme and user provider.
Default user provider(users) is an old app also deployed as a single module(web)

We created an enterprise base theme that have not only theme things but the control flow to base authentication like login and base error handling as the validation of not logged users raise exceptions.

Then we ended up with 3 web apps depending of each other, what we don't want.

I used the OnAuthentication in our base app template;
All the screens involved with error handling and user login, user info, my info, that were created on app creation we changed to be just web blocks and the template are empty screens with this web blocks, this way we just need to maintain the web blocks on base theme and not adjust all the apps we have.

And we don't want traffic over apps like base theme as the OS use then if we have components shared over apps, like images and screens.

We have scenarios like web blocks having different images and some times behavior over apps created based on same theme.

This time we also were not considering make another back-office app.

I will be glad if you can agree with this simple separation as i think it is fundamental to evaluate this on our environments without circular refs between apps.

On our clone we don't see any impact on this change.

This kind of change i don't plan to put on your original version at all. It will still be using default user provider and default theme and i will maintain it just on our clone.

If i upload and configure a new version to be a development version to you make revision and to adjust other app that depends of this app like the "Try now" deployed over your personal account, the people that choose use this forge component will be directed to use de one defined as current and stable and not the last one?