diff --git a/kinde_fastapi/framework/fastapi_framework.py b/kinde_fastapi/framework/fastapi_framework.py index 8dfe0668..d9837ae3 100644 --- a/kinde_fastapi/framework/fastapi_framework.py +++ b/kinde_fastapi/framework/fastapi_framework.py @@ -131,7 +131,15 @@ async def get_current_user(): @self.app.get("/login") async def login(request: Request): """Redirect to Kinde login page.""" - url=await self._oauth.login() + # Build login options from query parameters + login_options = {} + + # Check for invitation_code in query parameters + invitation_code = request.query_params.get('invitation_code') + if invitation_code: + login_options['invitation_code'] = invitation_code + + url = await self._oauth.login(login_options) self._logger.warning(f"[Login] Session is: {request.session}") return RedirectResponse(url=url) diff --git a/kinde_flask/framework/flask_framework.py b/kinde_flask/framework/flask_framework.py index 2b2b9246..a0ce4cdb 100644 --- a/kinde_flask/framework/flask_framework.py +++ b/kinde_flask/framework/flask_framework.py @@ -127,7 +127,16 @@ def _register_kinde_routes(self) -> None: def login(): """Redirect to Kinde login page.""" loop = asyncio.get_event_loop() - login_url = loop.run_until_complete(self._oauth.login()) + + # Build login options from query parameters + login_options = {} + + # Check for invitation_code in query parameters + invitation_code = request.args.get('invitation_code') + if invitation_code: + login_options['invitation_code'] = invitation_code + + login_url = loop.run_until_complete(self._oauth.login(login_options)) return redirect(login_url) # Callback route diff --git a/kinde_sdk/auth/login_options.py b/kinde_sdk/auth/login_options.py index 7ca43da4..3c87ec06 100644 --- a/kinde_sdk/auth/login_options.py +++ b/kinde_sdk/auth/login_options.py @@ -27,6 +27,10 @@ class LoginOptions: PLAN_INTEREST = "plan_interest" PRICING_TABLE_KEY = "pricing_table_key" + # Invitation parameters + INVITATION_CODE = "invitation_code" + IS_INVITATION = "is_invitation" + # Additional parameters container AUTH_PARAMS = "auth_params" SUPPORT_RE_AUTH = "supports_reauth" \ No newline at end of file diff --git a/kinde_sdk/auth/oauth.py b/kinde_sdk/auth/oauth.py index 1c22eb99..174a438b 100644 --- a/kinde_sdk/auth/oauth.py +++ b/kinde_sdk/auth/oauth.py @@ -280,6 +280,9 @@ async def generate_auth_url( # Registration params LoginOptions.PLAN_INTEREST: "plan_interest", LoginOptions.PRICING_TABLE_KEY: "pricing_table_key", + # Invitation params + LoginOptions.INVITATION_CODE: "invitation_code", + LoginOptions.IS_INVITATION: "is_invitation", # Re-authentication support LoginOptions.SUPPORT_RE_AUTH: "supports_reauth", } @@ -307,10 +310,19 @@ async def generate_auth_url( # Handle boolean parameters if option_key == LoginOptions.IS_CREATE_ORG or option_key == LoginOptions.HAS_SUCCESS_PAGE: search_params[param_key] = "true" if login_options[option_key] else "false" + elif option_key == LoginOptions.IS_INVITATION: + # Only add is_invitation if it's truthy + if login_options[option_key]: + search_params[param_key] = "true" else: # Use string representation for query params search_params[param_key] = str(login_options[option_key]) + # Handle invitation code: automatically set is_invitation to "true" when invitation_code is present + if LoginOptions.INVITATION_CODE in login_options and login_options[LoginOptions.INVITATION_CODE]: + if LoginOptions.IS_INVITATION not in login_options or not login_options[LoginOptions.IS_INVITATION]: + search_params["is_invitation"] = "true" + # Add additional auth parameters if LoginOptions.AUTH_PARAMS in login_options and isinstance(login_options[LoginOptions.AUTH_PARAMS], dict): for key, value in login_options[LoginOptions.AUTH_PARAMS].items():