diff --git a/auth0/authentication/get_token.py b/auth0/authentication/get_token.py index 9de89291..a7321b88 100644 --- a/auth0/authentication/get_token.py +++ b/auth0/authentication/get_token.py @@ -125,6 +125,7 @@ def login( realm: str | None = None, audience: str | None = None, grant_type: str = "http://auth0.com/oauth/grant-type/password-realm", + forwarded_for: str | None = None, ) -> Any: """Calls /oauth/token endpoint with password-realm grant type @@ -152,9 +153,16 @@ def login( grant_type (str, optional): Denotes the flow you're using. For password realm use http://auth0.com/oauth/grant-type/password-realm + forwarded_for (str, optional): End-user IP as a string value. Set this if you want + brute-force protection to work in server-side scenarios. + See https://auth0.com/docs/get-started/authentication-and-authorization-flow/avoid-common-issues-with-resource-owner-password-flow-and-attack-protection + Returns: access_token, id_token """ + headers = None + if forwarded_for: + headers = {"auth0-forwarded-for": forwarded_for} return self.authenticated_post( f"{self.protocol}://{self.domain}/oauth/token", @@ -167,6 +175,7 @@ def login( "audience": audience, "grant_type": grant_type, }, + headers=headers, ) def refresh_token( diff --git a/auth0/test/authentication/test_get_token.py b/auth0/test/authentication/test_get_token.py index f2c0b34c..7e91f638 100644 --- a/auth0/test/authentication/test_get_token.py +++ b/auth0/test/authentication/test_get_token.py @@ -189,6 +189,22 @@ def test_login_simple(self, mock_post): }, ) + @mock.patch("auth0.rest.RestClient.post") + def test_login_with_forwarded_for(self, mock_post): + g = GetToken("my.domain.com", "cid", client_secret="clsec") + + g.login(username="usrnm", password="pswd", forwarded_for="192.168.0.1") + + args, kwargs = mock_post.call_args + + self.assertEqual(args[0], "https://my.domain.com/oauth/token") + self.assertEqual( + kwargs["headers"], + { + "auth0-forwarded-for": "192.168.0.1", + }, + ) + @mock.patch("auth0.rest.RestClient.post") def test_refresh_token(self, mock_post): g = GetToken("my.domain.com", "cid", client_secret="clsec")