Authentication and Authorization with AWS API Gateway from MobileApp (Android + IOS) - amazon-web-services

User can sign in using any of the following from the Mobile App:
a. Facebook ID
b. Google Id
c. Apple Id (for IOS)
d. Mobile No
e. Email Id
Now, if the user tries to sign in using any of the Social Media Login, the information will be checked back in the database (DynamoDB) before allowing the user further accessing the other microservices.
if the user tries to login using mobile no or email, then the information will be checked back in the database (DynamoDB), and if exists, then it is followed by a OTP for verification.
How to design a robust authentication and authorization structure which may help with the following:
a. Security (must)
b. Performance (must)
c. Token may contain necessary information like userid, name etc, if possible
d. Invalidate, if possible
Possible Tech Stack : Mobile Apps -> API Gateway -> Lambda -> DynamoDB

Related

Alexa Skill with Azure AD B2C Auth expires after an hour

I am currently building an Alexa skill backed by Azure Functions (.NET Core/C#) and Azure AD B2C for authentication.
For the initial setup, I used mostly used the instructions found in this arcticle. Since, the article was written a couple of years ago, I had to make a few changes. In the end, I landed on the following configuration:
Azure Active Directory B2C
As I mentioned, we are using AAD B2C for authentication. Users of a related application are able to sign-up and sign-in to a React application. The idea is to provide an alternative interface for said users through Alexa intents + utterances.
I created an application for Alexa in AAD B2C with the following settings:
Properties
Web App / Web API: Yes
Allow implicit flow: Yes
Reply URLs: I entered the values provided by the Alexa skill setup (e.g. https://pitangui.amazon.com/api/skil/link/...); there are three different ones. I also added one for my azure function app (this is something that could be incorrect. It was part of what I did while diagnosing other earlier problems); it's in the format: https://myfuncname.azurewebsites.net/.auth/login/aad/callback (Do I even need this???)
App ID URI: https://myorg.onmicrosoft.com/alexa
Include native client: No
Keys
I generated a single App Key, which I'm using as the Secret in the Account Linking section in the Alexa Developer Console.
Many of the examples online mention setting an explicit expiration date here of 1 or 2 years; however, I am not presented with any options at all (i.e. no expiration option), just the code. Could this be part of the problem???
API Access
In the Published scopes section, the Scope's name is user_impersonation. The description is "Access this app on behalf of the signed-in user". The full scope value is: https://myorgsname.onmicrosoft.com/alexa/user_impersonation.
For API Access, I have to API entries here:
One that uses the user_impersonation scope mentioned above.
The second, titled "Access the user's profile", uses:
Acquire an id_token for users (openid)
Acquire a refresh_token for users (offline_access)
AAD B2C User Flow
The user flow that I'm using allows signing up and signing in, it utilizes the following configuration:
Properties
Misc
Enable JavaScript enforcing page layout (preview): On
Token lifetime
Access & ID token lifetimes (minutes): 60
Refresh token lifetime (days): 14
Refresh token sliding window lifetime: "Bounded".
Lifetime length (days): 90
Token compatibility settings
Issuer (iss) claim: https://<domain>/<b2c-tenant-guid>
Subject (sub) claim: ObjectID
Claim representing user flow: tfp
Session behavior
Web app session lifetime (minutes): 1440
Web app session timeout: Rolling
Single sign-on configuration: Tenant
Require ID Token in logout requests: No
Azure Function Authentication Middleware
For the authentication layer within the Azure Function, I'm utilizing the method described in the article mentioned above.
Alexa Developer Console
On the Alexa side of things, I have a really simple skill setup with the following settings:
Endpoint
My endpoint uses the HTTPS option with the default region set to the fully-qualified HTTPS endpoint of my Azure Function App's handler function.
The certificate set to "My development endpoint is a sub-domain of a domain that has a wildcard ..."
Account Linking
The account linking settings are as outlined below:
Do you allow uses to create an account or link to ...: Toggled On
Allow users to enable skill without account linking: Toggled On
Allow users to link their account to your skill from within your application or website: Toggled Off
Auth Code Grant: On
Authorization URI: https://myorg.b2clogin.com/myorg.onmicrosoft.com/oauth2/v2.0/authorize?p=<sign-in-user-flow-policy-name>
Access Token URI: https://myorg.b2clogin.com/myorg.onmicrosoft.com/oauth2/v2.0/token?p=<sign-in-user-flow-policy-name>
Your Client ID: AAD B2C App GUID
Your Secret: Key generated in App settings in AAD B2C for my Alexa Skill App (mentioned in the AAD B2C setup info above).
Your Authentication Scheme: HTTP Basic
Scope: openid and https://myorg.onmicrosoft.com/alexa/user_impersonation
Domain List: login.microsoftonline.com and myorg.b2clogin.com Note: This is probably wrong as I didn't know what to put here. The article above doesn't mention this setting at all
Default Access Token Expiration Time: 3600
Note: The Alexa Redirect URLS at the bottom are what I put in AAD B2C for the Reply URL section.
The Problem
Now for the most important part, The Problem. Everything seems to work at first...I'm able to go to alexa.amazon.com and utilize Link Account (which redirects me to and from my AAD B2C-driven login screen). Once I link accounts, I'm able to successfully utilize an utterance and receive a reply.
The problems starts when I wait an hour (I believe it's an hour). Attempting to initiate the Intent after an hour yields an error on the Azure Function app side of things when it tries to validate the Auth Token.
Can anyone provide me some guidance as to what I may have setup incorrectly or at least some things that I should look into? As I mentioned at the start of this question, many of the references that I'm finding online are out-of-date and do not cover all of the settings that I'm expected to utilize. Many of them are still using microsoftonline.com authority vs. b2clogin.com.
At a glance, I would assume that the problem is that the Alexa skill is failing to refresh its token after it expires after an hour. What do I need to do to ensure that it refreshes correctly?
I think that I have enough information at this point to go ahead and answer my own question. What I found was that the offline_access scope is necessary for Token Refresh to be possible.
Per Microsoft, "The offline_access scope gives your app access to resources on behalf of the user for an extended time. On the consent page, this scope appears as the "Maintain access to data you have given it access to" permission. When a user approves the offline_access scope, your app can receive refresh tokens from the Microsoft identity platform token endpoint. Refresh tokens are long-lived. Your app can get new access tokens as older ones expire.".
You can read more about it here.
To resolve the issue, I ensured that this scope was available in AAD B2C and added it as a referenced scope in the Alexa developer console.
Thanks for giving insight on offline_access. It took few hours to figure out how to implement offline_access. Interestingly offline_access works only with Azure AD, OAuth 1.0 endpoint and not with 2.0.
While trying with 2.0 it kept failing while account linking when multiple scopes were mentioned in Alexa configurations. The scopes I tried were as follows.
https://samplealexabackendapi/
https://graph.microsoft.com/offline_access
Finally I ended up working with OAuth 1.0 endpoint and using the scope https://samplealexabackendapi/.default which considers all scopes available to the app registered.

Django API fronted by Azure API gateway

I have a Django application that currently stores user credentials and performs authorization and authentication. I am in the process of breaking off the front-end into an Angular SPA and converting the backend to a REST API. My Django API will live as an Azure API app protected by Azure API Gateway. I would like to remove the authentication piece from Django and allow users to sign in using OpenID Connect through either Google or Microsoft Account. What I would like to happen is this:
When a user visits the site, assuming they have never registered with my app, they will have the option to sign in with their Google account or Microsoft Account. If the user decides to sign in using their Google or Microsoft account, (this is where I'm confused and why i'm posting here ... ) I think what happens is the API Gateway performs the authentication, generates a JSON Web Token (JWT), and sends that token back to the Django API. Django receives the JWT, decrypts it, and checks to see if there is a user account matching the email address in the JWT. If there is not a user account, Django will add a user to the user accounts table (not storing a password). If there is a user matching that email address, then Django allows the user in.
All that said, I guess my question(s) are:
Should I do the authentication at the API Management Gateway or should I do it at the Azure Web API?
Can I use Django's built-in authentication system to do what I want or is that not needed?
Am I over-complicating all of this? Is there an easier way to do this? All this seems like a lot of work.
Is OpenID Connect what I should be using (instead of Oauth2)? I have no experience with either.
Azure API Management does not actually provide any kind of JWT issuing mechanism, so you'll have to implement that yourself. The end points for doing that may or may not be exposed via API management.
What possibly gets you confused is the fact that the APIm Portal supports various indentity providers, like Twitter or Google, to sign up for the API. But these are not your application users, these are for the API Portal Users.
What you can do with the APIm Gateway is to validate subsequent calls to your backend API that the supplied JWT token is valid (using the <validate-jwt> policy).

Does Google Apps Email Migration API v2 support 2 legged oAuth1?

Does the Google Apps Email Migration API v2 support 2 legged oAuth1?
I've looked at this answer, but I believe it refers to the older version of the Email Migration API: Does Google Apps Email Migration API support 2 legged oAuth?
I have been able to authenticate an Email Migration API request using OAuth1 w/ tokens, but all of my 2 legged OAuth 1 attempts have failed. I have tried including xoauth_requestor_id and it has not had an effect.
There is some hinting in the docs that OAuth1 w/ tokens may be required, but I was hoping to confirm that that is the case.
For example the docs say: "If your application has certain unusual authorization requirements, such as logging in at the same time as requesting data access (hybrid) or domain-wide delegation of authority (2LO), then you cannot currently use OAuth 2.0 tokens. In such cases, you must instead use OAuth 1.0 tokens and an API key."
It seems clear there that "tokens" are referenced, however the word "token" is also used to describe the Authorization request header, so it is less clear that this means OAuth1 request tokens.
Any help is greatly appreciated. Thanks!
The section you are referring to doesn't seem up to date. You can have domain-wide delegation of authority using OAuth 2.0. It's called Service Account. Once authenticated, you do exactly the same that you used to do with 2-legged OAuth 1.0.
Here are the steps you need to get started:
Go to Google Developer Console
Create a project if you don't already have one
Go to APIs & auth --> APIs and activate the Admin SDK
Go to APIs & auth --> Credentials and click CREATE NEW CLIENT ID
Select Service Account and click Create Client ID
Download the p12 private key file (and keep it safe !)
Go to your Google Apps Admin Panel
Go to Security --> Advanced Settings --> Manage OAuth Client Access (Direct URL: https://admin.google.com/AdminHome?#OGX:ManageOauthClients)
Enter the Client Id you just created along with the scopes you'll need, separated with commas (In your case, https://www.googleapis.com/auth/email.migration)
Go to your favorite language client library documentation and find how to authenticate using the private key file you downloaded earlier and also impersonate your domain users.
Hope that helps.

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.

Howto secure a webservice using ONLY Facebook for authentication/authorizastion?

Setup
1. A LAMP web application that uses SOLELYFacebook for authent./author
(i.e. NO credentials set/asked by the web app)
2. A smartphone app that uses ONLY Facebook for authent./author.
3. A web service provided by -1- for -2- to communicate. https, of course.
4. A client-side Javascript that uses the same web service (-3-) for asynchronous CRUD
Use-Case:
A. The user signs in to - 1 - and Facebook id is saved on
server-side as well as a custom id.
B. The user signs in to - 2 - and the same happens on client-side.
C. The user enters data into - 2- which is stored locally.
D. Now comes the tricky part: 2 must send the data to 1 via 3.
E. Now even trickier: 4 must do the same.
My problem:
My problem is to find a strategy to authenticate & authorize communication in D & E. It would be easy if the user was to enter credentials. These would be stored locally and he was the trigger. And he only! However, when using solely Facebook for auth/author., authent. NEVER occurs on client-side. Thus, as far as I understand, the server has to provide some kind of legitimization. This would be, for example, a key or a token.
My question:
How is the client app -3- supposed to initially authenticate the user to the server (facebook id?)? How can I prevent someone from sending facebook id to the server service and, thus, getting access to the CRUD? Is some sort of an application key (like facebooks access token) sufficient?
If so, what about -4- the Javascript in the browser? Where to store the application key? Wouldn't it be too easy to steal that token, use it for authentication to -1- and then get access to all data of a certain facebook user?