{"record":{"id":"7e5e4aa93092fb4b","repo":"microsoft/semantic-kernel","slug":"refresh-tokens-not-supported","errorCode":null,"errorMessage":"Refresh tokens not supported","messagePattern":"Refresh tokens not supported","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"python/samples/demos/mcp_with_oauth/server/mcp_simple_auth/simple_auth_provider.py","lineNumber":266,"sourceCode":"        # Check if expired\n        if access_token.expires_at and access_token.expires_at < time.time():\n            del self.tokens[token]\n            return None\n\n        return access_token\n\n    async def load_refresh_token(self, client: OAuthClientInformationFull, refresh_token: str) -> RefreshToken | None:\n        \"\"\"Load a refresh token - not supported in this example.\"\"\"\n        return None\n\n    async def exchange_refresh_token(\n        self,\n        client: OAuthClientInformationFull,\n        refresh_token: RefreshToken,\n        scopes: list[str],\n    ) -> OAuthToken:\n        \"\"\"Exchange refresh token - not supported in this example.\"\"\"\n        raise NotImplementedError(\"Refresh tokens not supported\")\n\n    async def revoke_token(self, token: str, token_type_hint: str | None = None) -> None:\n        \"\"\"Revoke a token.\"\"\"\n        if token in self.tokens:\n            del self.tokens[token]\n","sourceCodeStart":248,"sourceCodeEnd":272,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/samples/demos/mcp_with_oauth/server/mcp_simple_auth/simple_auth_provider.py#L248-L272","documentation":"The MCP OAuth sample explicitly does not implement refresh-token rotation: load_refresh_token returns None and exchange_refresh_token raises NotImplementedError. Any client that obtains a refresh_token and POSTs to the token endpoint with grant_type=refresh_token hits this. It signals a capability gap of the demo, not a recoverable runtime fault.","triggerScenarios":"A token request with grant_type=refresh_token reaching exchange_refresh_token; an MCP client configured to auto-refresh expired access tokens against this sample provider.","commonSituations":"Using a generic OAuth client library that always attempts refresh when an access token expires (3600s expiry); pointing an MCP client expecting refresh support at this demo provider.","solutions":["Do not request or rely on refresh tokens against this sample — re-run the full authorization-code flow when the access token expires.","Configure the client not to send grant_type=refresh_token to this provider.","If you need refresh support, subclass SimpleAuthProvider and implement load_refresh_token/exchange_refresh_token with a persistent store.","Use a production-grade OAuth provider instead of this demo for workloads needing refresh."],"exampleFix":"# Disable refresh in the client, or subclass to implement it:\nclass MyProvider(SimpleAuthProvider):\n    async def load_refresh_token(self, client, refresh_token):\n        return self.refresh_tokens.get(refresh_token)\n    async def exchange_refresh_token(self, client, refresh_token, scopes):\n        # issue new access token, rotate refresh token\n        ...\n","handlingStrategy":"try-catch","validationCode":"# Detect refresh-token support before calling exchange_refresh_token.\nrt = await provider.load_refresh_token(client, refresh_token)\nif rt is None:\n    # refresh not supported -> restart the auth-code flow\n    raise RuntimeError('refresh not supported; re-authorize')","typeGuard":null,"tryCatchPattern":"try:\n    token = await provider.exchange_refresh_token(client, refresh_token, scopes)\nexcept NotImplementedError:\n    # re-run the full authorization-code flow to get a new access token\n    ...","preventionTips":["Do not request refresh_token scope against this sample provider.","Disable auto-refresh in your OAuth client when targeting the demo.","Re-authorize when the 3600s access token expires.","If you need refresh, switch to a production provider or subclass and implement it."],"tags":["oauth","mcp","authentication","refresh-token","not-implemented","demo"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}