"email" vs "Email" in AWS Cognito - amazon-web-services

In my AWS Cognito App Client settings, it offers me two settings for email: one with a capital E (Email), and one with a lowercase e (email). See screenshot below.
What is the difference between them?

Assuming you referring to the "Email" listed under Scopes vs. the "email" listed under Attributes:
Uppercase Email is a Scope and lowercase email is an attribute.
OpenID defines an attribute as "The base of the information model used to describe the Identity Data, for the purpose of exchanging it."
A Scope is used to group Attributes. A Scope defines what resources can be accessed via an OAuth2.0 guarded endpoint.
See more info here
In this screenshot, you are defining Read/Write ability over those specific attributes. Attributes you cannot mark as writeable are Required fields.
EDIT: An App Client provides an avenue for you to call unauthenticated APIs for registration, password resets, sign in, etc.
If you uncheck a scope under Readable or Writeable you will notice all attributes associated with that scope also uncheck, or you turn off individual attributes.
By unchecking you are disabling the ability for those fields to be received (read) or modified (write) through the API.
Why would you want to do this?: let's say you have a mobile app, web app, and a fat client/server side application sharing the same user pool. you would not necessarily want all three to have the same permissions when talking to the unauthenticated APIs. An App Client allows you to create an individual connection with tailored permissions per App Client ID.
See here for more info.

Related

How to debug Cognito's idpresponse endpoint

I'm setting up OIDC provider for Cognito User pool. The open id connect service I'm using is Paypal. At the step where paypal issues code and redirects to cognito's /oauth2/idpresponse endpoint after which cognito is supposed to exchange the code for access token, I'm receiving "Exception processing authorization code" error. As you can see the error message is not very discriptive.
I have no idea what I'm doing wrong. I did setup open id connect properly. Setup client settings in cognito and etc.
These are the endpoints I'm using for openid connect:
https://www.sandbox.paypal.com/signin/authorize
https://api.sandbox.paypal.com/v1/identity/openidconnect/tokenservice
https://api.sandbox.paypal.com/v1/oauth2/token/userinfo
https://api.sandbox.paypal.com/v1/oauth2/certs
In app client settings I have auth code grant flow and implicit flow enabled. I have custom domain setup. I provided paypal client id and secret
My guess is if I'm able to somehow debug idpresponse endpoint I should be able to solve the problem. Is there any way to do that? Maybe cloudwatch?
I don't know about debugging Cognito's endpoints, but I had the same problem and fixed it by doing the following:
Go to your User Pool in AWS.
In the side navigation under Federation, select Attribute mapping.
Click the tab of the identity provider you're having issues with (in my case it was Google).
There should be three columns, Capture, Google attribute, and User pool attribute. Make sure all of the attributes that are checked in the Capture column are mapped to an attribute in the User pool attribute column.
UPDATE:
After submitting this answer, I realized that the checkboxes in the Capture column are not checked by default. If you marked any attributes as required in the Attributes section of your user pool, then you need to map those attributes to the attributes provided by your external identity providers.
For example, I marked email as a required attribute in my user pool settings. So, when I added Google as an identity provider, I had to go to Federation->Attribute mapping, click on the tab for Google, check the box in the Capture column next to email, and select Email from the dropdown box in the User pool attribute column.
After taking these steps, the sign in work-flow worked for me.
My guess is the auth flow works just fine between Cognito and your identity provider, but Cognito doesn't know how to map the attributes returned from the identity provider to the attributes you have set in your user pool (in General settings->Attributes under the Which standard attributes are required section).

End user authentication for RESTful web services

I have an internal-facing RESTful web service. There are various client applications using the service, and the client apps themselves have end users. The web service needs to authorize requests based on the end user identities.
The question: What are the typical options for authenticating the end user here? That is, I want to authenticate the user, not the client application. (I don't mind if authenticating the client application is part of the scheme, but ultimately I need to know that the end user is who I think he or she is.)
One possible scheme, for example, would be to have per-client system accounts, and then have the client simply assert the user's identity (e.g. in an HTTP request header, say). So we authenticate the client application and delegate user authentication to the client. I don't think this is a very strong scheme, though, because it depends too much on keeping the system account credentials secret. I have seen too many examples of people e-mailing system account credentials around to put much faith in this sort of approach.
Another approach might be to have the client app, upon user login, use the user's credentials to get a token from the API, and then use that token for subsequent API requests. That way the authentication is user-specific without requiring the client app to hang onto the username/password credentials.
Anyway I'd like to have a better sense for the range of options I should be considering here.
The problem that you describe with "delegated authentication" is a real one. It means that a "client application" using it's credentials has access to the whole breadth of user data. This access can be used maliciously (for example a "semi-trusted" app harvesting api data) or negligently (for example an app accidentally exposing a Direct Object Reference Vulnerability - https://www.owasp.org/index.php/Top_10_2010-A4-Insecure_Direct_Object_References)
Probably the most prevalent "token based" scheme is OAuth2 (http://oauth.net/2/), and the precursor, OAuth, which many sites choose to continue to use.
OAuth2 has a number of roles:
resource owner (the user in your case)
resource server (your api)
client (the apps you talk about)
authorization server (not clear who or what would fulfil this role in your case)
The basic scheme is that the resource owner authenticates using their credentials directly with the authorization server. They are then asked if they want to grant some information (which may just be a persistent identifier, or a description of the information exposed by your api) to some client. When they accept an 'auth code' is sent to the client and they use that (combined with their own credentials) to receive an 'access token'. This access token can then be used to authenticate against the resource server (which can check it's authenticity back against the authorization server).
Normally the way this is used is that the authorization server and the resource server are owned and managed by the same entity (for example google and facebook would fulfil this role) and then clients are independently managed.
The scheme can also be used internally within an organisation without the "explicit grant" which can still at least confirm that a specific end-user is present before releasing any data from an api.

OAuth 2.0 client ids in Django/tastypie implementation

I'm trying to implement OAuth 2.0 for my API. I'm using a third party library to act as the basic OAuth provider, django-oauth2-provider,
and Tastypie as the framework. Those details shouldn't matter too much. The OAuth 2.0 works -- when a user is created, an OAuth 2 client
that manages the user's secret_key and their id is created. A customer can then supply the user ID they get back from the user creation
endpoint along with their username and password to get an access token which allows them to use API endpoints.·
Where I run into issues is retrieving the client id (which must be passed into requests for the access token). Obviously when a user is first created
I can return the client_id with the HTTP response. After that, however, there will obviously be cases where the user doesn't have their client id·
stored locally (this is a traditional user/app setup, not something like Google APIs where your client id is always visible). I want to protect
GET requests to the customer resource with OAuth, but that means I can't query the API for a given user's client ID. And it seems like the whole point
of OAuth is defeated if I can always just pass in a username and password to retrieve my client id from some oauth endpoint. Am I thinking about this wrong?
Also, from reading the OAuth specs I'm under the impression that a client id and client secret are all that should be supplied for getting granted an access token. Yet the implementation I'm using defaults to forcing the user to supply a client id, client secret, username, and password. I've overridden the implementation to require only the client id and secret, but I want to make sure that was the right call and I'm not missing something.
Edit for flup's response:
I'm dealing with a Django API as the resource server, and a user of an iPhone app as the resource owner. The iPhone app is directly associated with the server -- in other words, there are no third parties involved here and no plans to involve them in the future; all software is ours. I would think that the password flow would be what I would need in that case. Indeed, that seems to be what django-oauth2-provider supplies by default. I'd like to stay somewhat in line with what they are doing to not have to completely reinvent the wheel.
The goal of oauth2 is to let the resource owner give a client a valet key which authorizes it to access certain resources on your server on his behalf.
If there are no third parties involved, there is no client to authorize and no need to use oauth2.
Instead, you could use the standard authentication mechanisms present in tastypie.

django-tastypie: why are api keys useful and how to support multiple auth schemes?

I'm designing a website in which people will sign on as users and potentially be in multiple groups, which come in a couple of different types. I wanted to both have a website that people can use directly, as well as expose an API that can be consumed by other websites.
What's the best way to implement a login system that works both for regular users of the site itself, as well as which allow API-consuming websites to seamlessly create an account on behalf of the user and allow the user to view their data both from my website and the API-consuming website?
I'm using Django 1.5, so I'm willing to customize the user model and all that. The API will be furnished using Tastypie.
EDIT: Honestly, my main problem is that I don't really understand when API keys are useful and how they coexist (if they do) with regular user logins.
Use case:
The first and use case for API keys is automation. You provide your api key (or commonly called token) to a 3rd party and voila, you can have the 3rd party do stuff for you. When you do not trust the 3rd party anymore, you can just revoke the api key or re-generate it. Api keys allow the user to initiate & authenticate the chain of actions by requesting the token via traditional authentication (e.g username/password), and then the user passes it on to the interested parties. See my little story about phone numbers at the end.
Why not use passwords?
Because you don't want to compromise your users on other websites and have them type their password there in order to use your APIs. If the 3rd party is compromised, then the user's communications or password are compromised.
Here are good resources:
What is token based authentication?
https://developers.google.com/google-apps/sso/saml_reference_implementation
Tastypie APIKey authentication
Django Tastypie: How to Authenticate with API Key
Api keys with tastypie
Here is a good starting point:
from django.contrib.auth.models import User
from django.db import models
from tastypie.models import create_api_key
models.signals.post_save.connect(create_api_key, sender=User)
This should take care of creating api keys thanks to the post_save signal. The second part is to allow more than one scheme for the authentication to fit your use case, so... onto MultiAuthentication:
from django.contrib.auth.models import User
from tastypie.authentication import BasicAuthentication, ApiKeyAuthentication, MultiAuthentication
from tastypie.authorization import DjangoAuthorization
from tastypie.resources import ModelResource
class UserResource(ModelResource):
class Meta:
queryset = User.objects.all()
resource_name = 'auth/user'
excludes = ['email', 'password', 'is_superuser']
authentication = MultiAuthentication(BasicAuthentication(), ApiKeyAuthentication())
authorization = DjangoAuthorization()
Other considerations
These are good practice to never leak sensitive data on the network:
do not do any user/password authentication without ssl or tls.
never use http basic authentication without ssl or tls.
lock down resources users shouldn't access to with permissions.
make sure your responses have correct cache-control headers
always allow users to reset/regenerate/delete their tokens / api keys.
a user need not have only one api key, you can have several of them; one for each 3rd party.
I use gmail so here is an example from https://security.google.com/settings/security (review permissions) where I can see how google openid is used:
Why should you use one api key for each 3rd party? is the same as why should you allow the user to have more than one api key and label them for a particular use?.
The answer is that if the api key is something you share just like your phone number, but you don't need to give the same phone number to all your friends (google voice FTW!).
case 1: one phone number.
If your friend misbehaves and gives it to a bunch of sales rep, you are going to be pretty annoyed. If your phone is the same, then whoever has it may share it with somebody else without your knowing. End results, all sales reps know your number... not so good. But you still want your mom to be able to call you, right? So you can't really change your number. Now imagine a more dangerous situation; you have a tab at the local pizzeria, and they know you by name / phone number. If someone gets your api key, they may impersonate you to order pizza and still charge you (you have a tab!).
case 2: multiple phone numbers:
If you have 100 numbers to you give to 100 different friends, not only can they contact you, but if a sales rep calls you on a particular number, you would know which of your friend gave it away and you can just cut that one number. Mom's now happy because she can tell you where to go for brunch. Your friend now decides to order pizza ... you can now trace it to your friend (or you should provide the pizzeria a number that none of your friend knows).
From a security standpoint there are two main classes of "API Keys" with different purposes for each:
A random API-key that acts sort of like a password and username combined: It is hardwired into client configuration files and is considered a secret. Simply by possessing this key, you have API access. Because the key represents a secret identifying the client (thus validating trust), the secret must be transmitted with every request. The connection must be trusted to ensure the secret is not intercepted, meaning all API access must require TLS/SSL. Often this approach is extended by only using the key on the first request, with the remainder of the connection performed using a rotating session key linked to the client's IP address (much like logging in on a website)
An asymmetric signature scheme: An asymetric cypher like DSA or RSA is used to create a secret key that is stored in the client's configuration. The secret is never shared on the network, and instead encrypts a hash of each API request. The server keeps a public key linked to each private key which decrypts each request's hash signature, and then creates its own hash of the request to validate against. This is the recommended and ideal way to perform API authentication because it does not require TLS/SSL and requires no session management policy.
I am not aware of an API authentication library for django and would recommend looking at the source code of Amazon AWS's HMAC asymmetric signature based approach for an excellent implementation.
I would design the system so that every request needs to have an API key. Ideally you put that in the Authorization header of every request. The API should be as purely RESTFul as possible, ie no session handling. I think thats very important for good API design.
Once that part is done, your users will access the site in exactly the same manor. However, they won't remember their API key, but only their credentials. So, have a login page that authenticates the user based on their credentials, then return the api key to be stored in the client's session. From then on all requests should be authorized with the API key.

jax-rs rest webservice authentication and authorization

I have a web application that needs to allow users using different webclients (browser, native mobile app, etc) to register. After signing in they can access restricted content or their own content (like entries they create, etc).
What I did so far: I created a jax-rs rest webservice (I'm hosting my application on glassfish) that exposes the following methods:
register - user POST's his desired username/password/email/etc; if username/email is unique, an entry for this user is created in the database (I'm using Hibernate for persistence)
login - user POST's username and password. If they are ok a UUID is created and returned to the user (this will be used as a token for future requests). I have a table called logedusers, with userID, token, validSince as columns.
Here is where it gets confusing for me.
Let's say that I have another method, getUserEntries, that should return all the entries made by the user. To make this clearer, there will be a Entry table with the following fields: entryId, userId, text.
What is the best approach here?
What i do now, is I make a get request and pass in the token like this:
localhost:8080/myApp/getUserEntries?token=erf34c34
Afterwards, if the token is valid, I get the userID from the logedusers table and based on that userId, get all the entries and return them as json.
Something like this:
#GET
#Path("getUserEntries")
#Produces(MediaType.APPLICATION_JSON)
public Response getUserEntries(#QueryParam("token") String token) {
String userId=getUserIdFromToken(token);
if (userId == null){
return Response.status(Response.Status.UNAUTHORIZED).build();
} else {
//get some data associated with that userId, put it in the response object and send it back
return Response.ok().entity(response).build();
}
}
However, what happens if I have more methods that provide data if they are called by a valid user?
I'd have to do this check at the beginning of every method.
I want to make this authorization process transparent
So, two major questions here:
Is this design ok? The whole authenticate with user/pass, server creates and stores and sends token to the user, user sends token on future requests.
What do I do if i have many endpoints that need to determine the identity of the calling user? Can I mark them with some annotations, use some sort of security provider / authenticator (where I can add my own logic for validating - eg check to see if the token isn't older than 5 days, etc).
Thanks
Is this design ok? The whole authenticate with user/pass, server creates and stores and sends token to the user, user sends token on future requests.
It's somewhat OK. The conceptual level isn't too bad (provided you're OK with self-registration at all) but the interface needs a lot of tweaking. While yes, POST to register and login is correct, for the rest of your webapp you should be pulling the identity information out of the context if you need it, and using role-based access control at the method level where you can.
Note that your container has a whole set of authentication and authorization-support mechanisms built in. Use them.
What do I do if i have many endpoints that need to determine the identity of the calling user? Can I mark them with some annotations, use some sort of security provider / authenticator (where I can add my own logic for validating - eg check to see if the token isn't older than 5 days, etc).
Do they need the identity? Or do they just need to know that the user is allowed to access them? If the latter, the easiest method is to put a suitable #RolesAllowed annotation on the method, at which point (with suitable configuration; see the JEE5 security docs). If the former, you need to get the HttpServletRequest object for the current action and call its getUserPrincipal() method to get the user's identity (or null if they've not logged in yet). This SO question describes how to go about getting the request object; there are a few possible ways to do it but I recommend injection via a #Resource annotation.
What I wouldn't do is allow users to normally provide their own identity via a #QueryParam; that's just wildly open to abuse. You can allow them to ask about other users that way, but then you need to decide whether you are going to tell them anything or not based on whether the current user is permitted to know anything about the other user. That's the sort of complex security problem that comes up in a real app, and is a good point for needing the current verified user identity.