Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

M2M Manual methods #152

Merged
merged 4 commits into from
Aug 10, 2023
Merged

M2M Manual methods #152

merged 4 commits into from
Aug 10, 2023

Conversation

vincent-stytch
Copy link
Contributor

@vincent-stytch vincent-stytch commented Aug 9, 2023

Add M2M Manual methods

@vincent-stytch vincent-stytch requested a review from a team as a code owner August 9, 2023 16:58
@vincent-stytch vincent-stytch changed the base branch from main to v/autogenbeforem2m August 9, 2023 16:58
Base automatically changed from v/autogenbeforem2m to main August 9, 2023 17:48
@vincent-stytch vincent-stytch changed the title [work in progress, do not review] M2M Manual methods M2M Manual methods Aug 9, 2023
def authenticate_jwt_local(
self,
session_jwt: str,
max_token_age_seconds: Optional[int] = None,
leeway: int = 0,
) -> Optional[MemberSession]:
) -> Optional[Tuple[Dict[str, Any], Dict[str, Any]]]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally I don't really care for Tuple because it's such a weak type (you have to just know what the ordering of returned items means).

Furthermore, you're changing the return type of the public interface, so this will break someone's flow. I think it's okay if you make some other helper function (you could consider a shared/ folder like we do for stytch-node), but this interface should not change.

# ENDMANUAL(authenticate_jwt_local)

# MANUAL(authenticate_m2m_jwt_local)(SERVICE_METHOD)
# ADDIMPORT: import time
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[sand] import time isn't used in this function

Comment on lines 132 to 135
def __init__(self, sub, scope, custom_claims):
self.sub = sub
self.scope = scope
self.custom_claims = custom_claims
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Add typing for everything
  2. But this method is unnecessary -- anything inheriting from pydantic.BaseModel will automatically be parseable and get an __init__ method for free
  3. But also this isn't a ResponseBase -- you're not going to have a status_code or request_id. Make this inherit from pydantic.BaseModel instead

client_secret: str,
scopes: Optional[List[str]] = None,
) -> Optional[GetTokenResponse]:
"""Rtrieves an access token for the given M2M Client.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[dust] spelling

Suggested change
"""Rtrieves an access token for the given M2M Client.
"""Retrieves an access token for the given M2M Client.

data["scope"] = " ".join(scopes)

url = self.api_base.url_for(
"/v1/public/" + self.project_id + "/oauth2/token", data
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use an f-string

Comment on lines 131 to 134
if required_scopes:
missing_scopes = filter(lambda scope: scope not in scopes, required_scopes)
if missing_scopes:
return None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use comprehensions instead of map/filter/reduce. Also, this can all be simplified.

One more nit-picky thing: I prefer to be really explicit with conditionals instead of relying on "truthy" values

required_scopes = required_scopes or []
missing_scopes = [scope for scope in scopes if scope not in required_scopes]
if len(missing_scopes) != 0:
    return None

def authenticate_jwt_local(
self,
session_jwt: str,
max_token_age_seconds: Optional[int] = None,
leeway: int = 0,
) -> Optional[Session]:
) -> Optional[Tuple[Dict[str, Any], Dict[str, Any]]]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Not a fan of tuples
  2. This breaks a public interface; let's create a shared helper

Comment on lines 156 to 159
def __init__(self, client_id, scopes, custom_claims):
self.client_id = client_id
self.scopes = scopes
self.custom_claims = custom_claims
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed

Comment on lines 392 to 395
def __init__(self, sub, scope, custom_claims):
self.sub = sub
self.scope = scope
self.custom_claims = custom_claims
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed

Copy link
Contributor

@logan-stytch logan-stytch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving to unblock. Remaining comments are really minor. Two things, though:

  1. You need to bump version.py
  2. Please add a screenshot of you manually testing M2M auth + sessions auth since we've refactored local authentication logic
    a. And related, add a Linear ticket (you can assign to me) for adding new automated tests


# Unpack the session claim to match the detached session format.
claim = payload[_session_claim]
) # Unpack the session claim to match the detached session format.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is outdated -- just remove it

self.clients = Clients(api_base, sync_client, async_client)

# MANUAL(m2m.token)(SERVICE_METHOD)
# ADDIMPORT: from typing import Any, Dict, List
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You also use Optional here

Fields:
- client_id: The ID of the client.
- client_secret: The secret of the client.
- scopes: An array scopes requested. If omitted, all scopes assigned to the client will be returned.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[sand] missing of in description

Suggested change
- scopes: An array scopes requested. If omitted, all scopes assigned to the client will be returned.
- scopes: An array of scopes requested. If omitted, all scopes assigned to the client will be returned.


# Unpack the session claim to match the detached session format.
claim = payload[_session_claim]
) # Unpack the session claim to match the detached session format.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is outdated -- just remove it

@@ -279,76 +280,33 @@ async def authenticate_jwt_async(
# MANUAL(authenticate_jwt_local)(SERVICE_METHOD)
# ADDIMPORT: import time
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This import is no longer used


# ENDMANUAL(GetTokenResponse)

# MANUAL(M2MJWTClaims)(TYPES)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add imports for any, dict, list, and optional

Comment on lines +15 to +22
def authenticate_jwt_local(
*,
jwks_client: pyjwt.PyJWKClient,
project_id: str,
jwt: str,
max_token_age_seconds: Optional[int] = None,
leeway: int = 0,
) -> Optional[GenericClaims]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You know, it would be really cool if we had a stytch/shared/test/test_jwt_helpers.py file :)
I think I'm empathetic if you don't want to do that right now, but could you at least go back and add a test in this PR summary to show that m2m auth + sessions auth are working as expected?

@vincent-stytch vincent-stytch merged commit 57912cb into main Aug 10, 2023
@vincent-stytch vincent-stytch deleted the m2m2 branch August 10, 2023 18:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants