Access user info from lambda - aws-lambda

I'm working on a serverless app with aws.
I use AWS Cognito User Pool to manage user : register, login, logout.
Once those users have been confirmed, I use AWS Cognito Identity Pool to get temporary credentials. Then I use those credentials to access the api (the endpoint on my api require AWS_IAM for Auth and call lambda).
All of that work perfectly. But I need to know which user has requested the action. In the lambda I can get the IdentityId from my Identity Pool. But I need to get attributes from my user in User Pool.
So my question is : is there a way to get a user from User Pool using the IdentityId of the Identity attached to it ? Or at least, get the access token ? I know I can send the access token in headers but I would like to only depend on the AWS_IAM auth.

Getting from a federated identity_id back to the user pool user is tricky because there's no guarantee it is a user pool user (it could well be someone from Facebook, or even an unauthenticated user- depending on your configuration).
Given an IdentityId you can use identity:GetOpenIdToken to get a valid OpenId token (you can ignore the logins part of the request if you are just using UserPools).
You can then use this token against the userpools:GetUser end point.
There's a few pitfalls here, like ensuring you authenticate with a scope that allows you to see all the attributes you care about. If you haven't, then you'll need to use the username returned with userpools:AdminGetUser to get the full user profile.

Related

How to access user specific resources in webapi when the access token does not include user info

I have implemented OpenId Connect for authorizing my multi tenant app, I have obtained both the Id Token and the access token. The access token does not contain any claims, but I would like to access user specific resources in the web api.
For example, in order for a user to access a certain resource, 1. They must be a tenant admin and 2, they must have permission for that resource (say a specific job post).
My questions.
Do I send the user permissions to the webapi in the request body/query and the webapi trust those permissions?
Should I use the access token to call the Identity Server to get the user information, then proceed if the user has the permissions?
Any other options?
You can always add the necessary user claims inside the access token, and by doing that, you don't have to pass that information separately. You use ApiScopes and APiResources to control what user claims that goes into the access token.
See my answer here: ApiResource vs ApiScope vs IdentityResource
To complement this answer, I write a blog post that goes into more detail about this topic:
IdentityServer – IdentityResource vs. ApiResource vs. ApiScope

OneLogin programmatic session cookie validation - No browser

I have the following scenario that I am curious if it is possible to implement. I need to use SSO and more specifically OneLogin to authenticate the user via custom UI from my Java standalone application. I know this can be done via Create Session Login Token and then Create session via token One Login API calls. With some parsing I can get the session cookie out of the last call and store it.
Now I need to programmatically hit the API server, which is to be build still and this server somehow needs to validate the session cookie that I am going to send along with request. The key word "Programatically" as in there will be no browser
OneLogin doesn't provide SDK to validate existing session cookie => it would be nice if I could, based on session cookie find out if it is still valid and what is the user name used for this session. If session is invalid API server would return unauthorized.
Is this even possible? Or is it possible in some other way?
Basically One Login is already used in our ecosystem and I have to continue using it
The app that will log user in and get the session cookie may not be the one calling the API server. This could be another java application that would receive the session
I guess what I am looking for is Validate Session equivalent from Open ID Connect API in general API
The session_token that is returned via that API has a short expiry is only intended to be used for making the Create Session request which returns session cookies.
It sounds like OpenId Connect might be the best option for this use case. If you have user credentials then you could use the Resource Owner Password Grant flow to authenticate the user and obtain an id_token.
The id_token is a JWT containing user details can then be verified for authenticity by checking its signature, audience and expiry claims. It can also hold other custom information about the user that may be used by your backend application.

Open ID Connect Session Management Access/Refresh Token vs Session iFrame

We have a web app in which we allow users to log into the app using any Open ID provider(e.g. Okta, Google, Facebook etc.). We want to implement the correct Open ID Connect prescribed methodology/workflow to keep the user logged into the site.
The existing implementation, looks at the expiry of the Access Token then if it's close to expiry uses a Refresh Token to get a new Access Token to keep the user logged in. I feel like this is wrong. When a user logs in to the web app, the Identity Token is used to Authenticate the identity of the user using the Authorization Code workflow. The Access Token and Refresh Token are stored on the server side. Periodically, the Refresh Token is used to get new Access Tokens to keep the user logged into the site. I believe this is a security risk because -
Imagine if a user is logged onto his OP account in a browser. He opens up Sky and is directly logged into MP because he’s already logged into MP. He then in a separate tab, logs out of his OP account. He will continue to be logged into MP for days on the basis of this Refresh Token/Access Token mechanism! Isn’t this a security risk?
If feel like the correct way to go about this is to use Session Management using iframes as prescribed here on OIDC -
https://openid.net/specs/openid-connect-session-1_0.html
For more context, when a user logs into our WebApp we pull data from the OP's UserInfo endpoint to create a profile within our WebApp and set permissions/roles within our app based on data sent over from the OP's UserInfo endpoint. We continue doing this periodically. For this purpose, I feel like using the Access Token(and using the Refresh Token to get new Access Token) to access the UserInfo API is correct because it conforms to the OAuth 2.0 concept of protecting/authorizing API/Resource endpoints using Access Tokens.
I want to know if this is indeed the correct way to manage how a user should be logged in when supporting Open ID Connect.
I think the first question is whether you want to bind the lifetime of an OpenID Connect provider Single Sign On session with the session of your application. You just want to authenticate a user using their OpenID Connect service. If I logout of Google, I expect to be logged out of GMail, but not a third-party application that used Google for authentication. Would you like to implement Single Sign Out as well?
But if I wanted to be logged out when you logout of the OpenID Connect provider, I would implement the OpenID Connect Session management. There is one thing good to be aware of when using iframes and cookies - browsers have an option to "Block third-party cookies" (that's how Chrome calls it), it's turned off by default, but as far as I know, it disables the SSO functionality when turned on.
I'm not sure why you request the userinfo endpoint periodically. If you just want to check whether the access token is still valid, you could also use the token introspection endpoint.
For security concerns, I would suggest you to read the OAuth 2.0 for Browser-Based Apps RFC. It recommends using the auth code flow with PKCE instead of the implicit flow. With the implicit flow, access tokens transported in redirect URLs stay in network and browser caches and can be used right away by an attacker. The auth code with PKCE needs a code_verifier (one-time secret) in order to be exchanged for tokens. So I would first check how the providers work with a configuration you choose and if it's even supported.

Yammer Rest API > Authentication based on server side script (php) without user interaction

My project has the requirement to access the yammer data using the given REST API using server side script(mainly PHP) and not involve a client side login using yammer's OAuth dialog.
I have gone through this document:
https://developer.yammer.com/docs/oauth-2
but this says, we requires user interaction.
What I wanted was can I generate a client_id and client_Secret to further generate access token to make API call out, but in all these processes I only use the authenticated users username and password in my server-side script.
Can anyone suggest a solution or is a client-side interaction required by design?
Thanks in advance!!
You have to have a user authorize the application at least once. This is just the nature of the OAuth implementation and you can't work around it. Having users go through the OAuth flow is considered a best practice.
If you have an OAuth token for a verified admin of Yammer, you can use impersonation to get tokens for end users without them interacting with the OAuth flow.
The below from Microsoft blogs might help you & added source at the end of answer.
Obtain a Verified Admin token for your application in one of the following 2 ways
a. Create the app with a Verified Admin account and then in the app’s Basic Info page, click “Generate a developer token for this application.” Note that you’ll need to use this app’s info in the JS SDK and any subsequent calls.
b. Use the process outlined at https://developer.yammer.com/docs/test-token with a Verified Admin account to get an OAuth token for that VA account. Note that you must use the app info used to generate this token in all future steps.
Obtain the current user’s email address in the server-side script.
Using the VA token obtained in step 1 to authenticate, pass the user’s email address to our Get User by Email Address endpoint documented at https://developer.yammer.com/docs/usersby_emailjsonemailuserdomaincom, and then process the response
a. If the call to the API endpoint returns a 200 OK response, first check the “state” field to make sure the user is “active” and if so, store the “id” field that’s returned and go to step 4
b. If the call returns a 404 or a state other than “active,” direct the user to finish creating and activating their account however you like.
Once you have the user’s ID, you can pass it to our Impersonation endpoint to obtain a pre-authorized OAuth token for that user. This endpoint is documented at https://developer.yammer.com/docs/impersonation and must use the VA token obtained in step 1 to authorize the call, and the consumer_key of your JS SDK app.
You now have an OAuth token for the current user. When generating the code being passed to the browser, have the client side JS SDK code first call yam.platform.getLoginStatus and if there’s no active session and you have a token from step 4, pass that token to yam.platform.setAuthToken($tokenFromStep4, optional_callback_function_if_desired(response)). If you don’t have a valid token, direct the user to finish setting up their Yammer account.
Continue making JS SDK calls as you normally would, without needing the user to authenticate.
Source: https://blogs.technet.microsoft.com/askyammer/2016/11/04/preauthorizing-the-yammer-js-sdk/

Changing password after successful login with Okta API

I'm currently building an application that uses Okta for authentication, and I'd like to build a feature that allows users to change their password once they've logged in. Unfortunately, I can't seem to find an endpoint that will serve this purpose. The main change password API, api/v1/authn/credentials/change_password only works for users currently in the PASSWORD_WARN, and PASSWORD_EXPIRED states. Is there any way to use this or another similar endpoint once the user has logged in?
Yes, in this case you'll want to look at the Users API (and specifically the Change Password section).
Generally, the /api/v1/authn/credentials/change_password endpoint that you mentioned in the prompt is strictly for the authn flow - it's the endpoint you use to transition the user from PASSWORD_WARN or PASSWORD_EXPIRED to the next authentication state (by providing a new password).
The /api/v1/users/:id/credentials/change_password endpoint can be called at any time by your backend service, and doesn't strictly require the user to be authenticated - it's not CORS enabled and you'll need to provide an ApiToken when sending a request to it.

Resources