p2-inc / keycloak-orgs

Single realm, multi-tenancy for SaaS apps
https://phasetwo.io
Other
389 stars 66 forks source link

Add organization through Registration #28

Closed rvmourik closed 1 year ago

rvmourik commented 1 year ago

Hi There,

Is there a way to let the user set an Organization (name) through the registration form? Or is creating Organization only available through the Keycloak admin or REST API?

Thanks in advance,

Robbert

xgp commented 1 year ago

Not currently. You can give users the create-organization role by default, and then have a check after authentication where you allow the user to create an organization using the API. This is how we do it in our self-service product.

However, it would certainly be possible to build a registration form to do what you’re asking, and we’d happily accept a PR with that.

rvmourik commented 1 year ago

Not currently. You can give users the create-organization role by default, and then have a check after authentication where you allow the user to create an organization using the API. This is how we do it in our self-service product. However, it would certainly be possible to build a registration form to do what you’re asking, and we’d happily accept a PR with that.

Thanks for the quick reply! You have custom code on the side of the Keycloak theme which does the API call? Or you redirect the user after registration to a part of your self-service product?

I am quite new to Keycloak, so haven't done much investigating how customizing works. Maybe in the future :-)

xgp commented 1 year ago

After the registration or login, we just call it from our application. If you are still having difficulty, I can post an example on Monday.

rvmourik commented 1 year ago

After the registration or login, we just call it from our application. If you are still having difficulty, I can post an example on Monday.

That would be very much appreciated, thanks in advance.

xgp commented 1 year ago

This uses keycloak-js and phasetwo-js to create a default org for a user after login if they don't have one:

// create and optionally configure the Keycloak instance
const keycloak = new Keycloak();
// function to get the access token, used by the API
const getAccessToken = () => keycloak.token;
// configuration for the API
const configuration = new Configuration({
  basePath: 'https://my-keycloak-host/auth/realms',
  accessToken: getAccessToken,
});
// create the API client
const orgs = new OrganizationsApi(configuration);

// set an event listener for authentication success. this is called after a successful redirect from keycloak to your app
keycloak.onAuthSuccess = function () {
  // check if there's a token and it's missing organizations. this will require that you've added the organization role mapper to the token in your client
  if (keycloak.tokenParsed &&
    'organizations' in keycloak.tokenParsed &&
    isObject(keycloak.tokenParsed?.organizations) &&
    isEmpty(keycloak.tokenParsed?.organizations)
  ) {
    //create the default org
    const orgName = `org-${nanoidDisplay()}`;
    const displayName = `${keycloak.tokenParsed?.email} default`;
    try {
      orgs.createOrganizationRaw({realm: realm, organizationRepresentation: {
        name: orgName,
        displayName: displayName,
      });
    } catch (e) {
      console.log('Error creating an organization.');
    }
  }
});
rvmourik commented 1 year ago

Thanks @xgp that's very helpfull

xgp commented 1 year ago

@rvmourik Let me know if you have problems with it. I trimmed it down from what's in my code, so I might have missed something.

rvmourik commented 1 year ago

@xgp do have a question related to this, in your code your accessing the organizations attribute from the token. I think this is the idToken or accessToken. However when I decode one of does two with jwt.io I don't see an organization attribute. I looked through all of the settings (I think) but I can't find a way to add this to te result. The test user is assigned to an organization and has all roles assigned to it's account.

xgp commented 1 year ago

@rvmourik that's what I meant with the comment in the code example that said

check if there's a token and it's missing organizations. this will require that you've added the organization role mapper to the token in your client

To add it to your token, go into your client (mine is called "dashboard" in the screenshots below), click on Client Scopes, click on the {client}-dedicated one (first one in the list). Select the Add mapper, By configuration dropdown, and select Organization Role from the list. Configure it with the organizations claim name, and make sure it's in the access token. Your config can set it up with a different name, and coming from another place like userinfo, but you'll have to change the code for that.

image

image

rvmourik commented 1 year ago

Ah Thanks, I saw the readme and that there was an OIDC Mapper. But like I said, I am fairly new to using keycloak so could not find where to make the configurations. If you want I can add your instructions to the repo's readme where to configure the OIDC mapper?

xgp commented 1 year ago

@rvmourik I'll keep this issue open and then build a wiki page based on what we've gone through. Thanks for having patience. I think we'll end up with a good guide that others can use.

rvmourik commented 1 year ago

@xgp

My patience is not tested, you reply within minutes haha :-)

If I can do anything to test your docs let me know if I can help.

ecasilla commented 1 year ago

Would it be possible to create the organization in keycloak after registration via a required action instead. Having the external app create the org is not ideal?

xgp commented 1 year ago

Hi @ecasilla it would be possible to write a required action that creates an organization. How you do it would depend on your specific requirements.