Monday, 19 March 2018

AWS Cognito User Pools, Lambda and Box integration

AWS Cognito User Pools, Lambda and Box integration


Feb 2022 - this post is permanently moved to https://architectfwd.com, my new site, and can be found here  - https://architectfwd.com/architecture/cloud/amazon-web-services-aws/cognito/user-pools/2022/01/23/aws-cognito-user-pools-lambda-and-box/ please go and bookmark that site for all of my future content.


In my previous posts I have been using Azure functions and B2C. I had a use case I wanted to try out and stood up an AWS Cognito user pool with 2 Lambda functions connecting to a box app using box sample code[1]. The process was simple and I managed to stand up the site really quickly, thus very impressed - I'd been keen on using Cognito for a while as an identity pool, and only created my AWS account the day before so all in all a great experience.

Here's what the solution would look like:


Cognito

I created a sign in / sign up policy similar to the B2C and the pool config was really easy. I created and linked up a box.com app.




I was then tasked with the box-specific lambda functions for post authentication and for creating the user in box.

Lambda 

2 Lambda and a couple of roles later and I was connected up. I used a sample angular app, wired up the AWS and box config and was A for away, except I had to increase the one of the function's timeout to 5 seconds once I stood up the angular app in Azure, it kept timing out. Cognito User Pool Lambda functions must respond within 5 seconds, not configurable.


I also needed to create roles for the Cognito and Lambda integration, specifically the first needed to be a service role, specifically a AWS lambda basic execution role. It probably needs Log policies. The second role needed a little more:



An API gateway was needed for lambda proxying to the token exchange function with box



I also needed an authorizer for the Cognito pools


CORS

CORS was a nuisance, I ended up writing headers back in all responses, just couldn't get it to work otherwise. the origin should not be a *, I know. I'll fix that, any anyway the box.com app config provides one more CORS setting which is tied to the correct domain.


Working app

It helped that I had some sample code from box. With all this configured I have a custom user pool of users who each get their own folder in a box.com instance where they can upload documents to.

I stood this up in an evening, really impressed by the AWS Cognito User Pool service and the simplicity of the interfaces. The lambda interface is awesome to use. Box.com app config is simple, and I am a long time box.com user so I think their user experience is great in general. 

Closing

I want to spend more time with AWS. I may continue with the Azure B2C as exploratory and rather throw my efforts in this direction.

References

[1] box samples on github


Cheers
Quintes


Connect with me on LinkedIn or Twitter

Wednesday, 21 February 2018

Azure Functions and Azure Active Directory B2C - part 2 - postman

Azure Functions and Azure Active Directory B2C (Part 2) - postman


In my previous post I setup an Azure function and B2C for auth. I wanted to now quickly get postman to use a token from B2C. In retrospect probably would have been quicker to build the SPA, will try that next. Quickly, not so much, as I worked through the screens and dialogs in B2C to setup apps and scopes, mostly getting this error when trying to get a token from within Postman.

AADB2C90205: This application does not have sufficient permissions against this web resource to perform the operation.

In the Azure Portal, Azure B2C, Applications, go to the app created previously (mine was called functionsapp). Ensure that the APP ID URI is something, in my instance called is spaapp.

Then lower down in that blade find "API Access", by default it will contain "access the users profile". Under published scopes it auto filled "user_impersonation" for me.

Create a Postman application in B2C

In the Azure Portal, Azure B2C, Applications, create an app for Postman

Give it a name, Web app (Yes), Implicit (Yes), Reply URL (https://getpostman.com/postman), App ID URI (/api), Native Client (No)

Then lower down in that blade find "API Access", by default it will contain "access the users profile". Click Add, and choose the name of your other app (in my instance functionsapp) and choose the scopes. Save.

Under published scopes I had nothing.

Postman - Get new access token screen 

I typed these in:

Token name : anything
Grant: implicit
Call back url: https://getpostman.com/postman
Auth URL : https://login.microsoftonline.com/tenant.onmicrosoft.com/oauth2/v2.0/authorize?p=b2c_1_signupsignin-01
Client id: 842....
Secret:
Scope : openid https://tenant.onmicrosoft.com/spaapp/user_impersonation offline_access
Client authentication: send client credentials in body

Fail, until I got that scope and app id URI correct.

Token received!

Test the function

Test the function in the postman, and 200 OK, and the function log show my header coming through, as expected from previous post (req.headers["x-ms-client-principal-id"])

Closing

On to the front end, less time in Postman.

References

[1] https://docs.microsoft.com/en-us/aspnet/core/security/authentication/azure-ad-b2c-webapi#configure-a-sign-up-or-sign-in-policy


Cheers
Quintes


Connect with me on LinkedIn or Twitter

Wednesday, 14 February 2018

Azure Functions and Azure Active Directory B2C - part 1

Azure Functions and Azure Active Directory B2C (Part 1)


Doing some work with azure functions and need authentication so I decided to try the B2C to setup an external Identity Provider.

I used [1], [2], [3] as reference.

Create a Azure AD B2C directory 

Create a new AD B2C directory, you cannot use an existing AAD directory.

Once done you want to set up policies. Do not go to Azure AD, it's not there, search in services for "Azure B2C", open that up and possibly favourite it so it is pinned on the menu.

If you did this as I did, the directory is not linked to a subscription. You need to go through MarketPlace, find B2C and choose the "Link an existing B2C to my subscription". Wait for that process and then go back to the B2C blade and view the Identity Providers and associated policies

Policies

Setup a basic sign in / sign up policy, specifying the idP, custom attributes and claims. I'm still going to integrate with another Provider, just want a basic case to work first.



Link an app

The purpose of this step is to configure an app to use the B2C directory.

A GUID will be generated.

Go back to the Sign up / sign in policy and grab the metadata endpoint URL


Go to the Function App, Function App Settings, Networking, Authentication/Authorisation and turn on the Authentication. Select "Azure Active Directory", Choose advanced and enter the GUID generated previously as well as the metadata endpoint url.

Save and wait for the notification "Save App Auth Settings"

Test the function

Test the function in the test window, you will have a 401 Unauthorized returned with error "Authentication is enabled for the function app. Disable authentication before running the function.".

Great, so grab the function URL and paste into a private browser session. You will be prompted to enter your existing email address and password, or signup. I chose the latter, and was presented with this form, which matches the fields I want captured:

I verified the account and the function was executed successfully! (Note I used the sample http trigger, which will become my secured cosmos db function)

This XML file does not appear to have any style information associated with it. The document tree is shown below.
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">Hello sgdfg</string>

I actually added the request headers to the response like this to test:

body: JSON.stringify(req.headers)

I get 4 headers, particularly this one, which has the display name I provided in signup. Not super useful

"x-ms-client-principal-name"

But I also get "x-ms-client-principal-id":"6f8132fc-..."

I will use that in the meanwhile, but want to exchange for claims.

Closing

It was easy enough to setup the B2C and the App, then linking a function so that the function can authenticate and authorise a user. Next is to read the claims within the function to ensure I can setup cosmos db documents per user.

References

[1] https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-reference-policies
[2] https://blogs.msdn.microsoft.com/appserviceteam/2016/06/22/app-service-auth-and-azure-ad-b2c/
[3] https://blogs.msdn.microsoft.com/hmahrt/2017/03/07/azure-active-directory-b2c-and-azure-functions/

Cheers
Quintes


Connect with me on LinkedIn or Twitter

Sunday, 28 January 2018

Provisioning Office 365 Services 01 - getting started

Provisioning Office 365 Services 01


I've just completed the Provisioning Office 365 Services course through edX, mostly as a result of a number of organisations asking me over the last 3 months if I had any knowledge or experience in O365.

Thus I now do, specifically using a trial for an E3 subscription to setup a basic tenant comprising Exchange Online, SharePoint Online, Office, Teams etc. I have not setup/configured InTune (noting I do have some prior experience from an solutions architect view for mobile platforms) or Skype for Business, nor intend to, as my goal was to understand the Subscription, Tenant, Domains, Email and Administration views, and hopefully get some context on Rights Management.

Creating the tenant  


It is important to note that you must select the region/country for the subscription data location AFAIK this cannot be changed.


Also choose a domain name which is onmicrosoft.com which you also cannot change - this is the default domain name associated with the subscription.

So how do I find out my tenant name /domain name and tenant ID after the fact? Open azure portal and find the Directory ID (Guid) here and the name of the tenant is the xxxxxx.onmicrosoft.com you are most likely currently logged in as when creating the subscription. Find it under Setup -> Domains if you are unsure.

While you are on the Organisation profile you may as well select the Release Track or remember to do it later if you want some users to be on the latest releases as they come out. Most likely you actually want to do this once there are some users, so moving on..

What does my subscription look like? Like the below:



Custom Domain


You'll need to setup the custom domain for your organisation before adding users. Do this from the Setup -> Domains


I'm skipping a few screens here, in the interests of not showing my settings, but after adding the domain you need to verify you own it. Do this via the TXT OR MX record option. I chose TXT and flew through it


As example of the Verification screen:



Once verified, which is super easy, you are presented with tables of the releveant DNS Entries to add. I really think the addition of the required DNS entries on screen is helpful to get you started quickly.


Users


Add a user (regular user or Administrative)


I wanted more rights, so the Roles can be edited to give me Admin, or a mixed set of Administrative roles. These are all well documented and I won't repeat the role descriptions here.


Groups

Add some groups, there are a couple of options including O365 groups, distribution lists, mail enabled security groups and security groups.



I created one called Accounts, which would be used elsewhere, and added a user or two

Closing


This is a good start - you've created the subscription, setup a custom domain, and added users and groups. If I can work through my other thoughts before my trial ends I'll put them up here so that I can remember, and perhaps they are useful to someone else.

Cheers
Quintes



Connect with me on LinkedIn or Twitter

Thursday, 2 November 2017

Mule ESB content routing example running on Mule Runtime in no time

Mule ESB content routing example running on Mule Runtime in no time


This is a quick overview on running a Mule app - the content routing example -  on the MuleSoft Mule ESB Runtime locally on an Ubuntu Linux machine.

I really wanted to see how difficult it was to get the runtime going and had little in the way of challenges. I would need to do some more tutorials on the backend flows and other more advanced examples before I put up another demo but wanted to see how much effort it took to get going.

Running Anypoint Studio and the Mule Runtime

On Ubuntu, the studio runs pretty good, Eclipse appears to be the base and the UI is as rich as expected.

I quickly crafted together the content routing, and getting it to run is also easy.



Downloading Mule Runtime 3.8 was easy, and I extracted and ran it locally without any additional configuration:
./mule

I couldn't find the built archive initially, but tracked it down from the logs. Once Mule started up, I went and copied the content routing archive to the /apps folder, and it exploded successfully:

[Mule.app.deployer.monitor.1.thread.1] org.mule.module.launcher.application.DefaultMuleApplication:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ New app 'mule-contentrouting'                            +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

In my browser I browsed  to http://127.0.1.1/?language=French and got the demo response.

I'll run through some more tuts and post awesome bits here, as I am keen to see how tough integration challenges I've seen can be simplified with this tooling

Cheers
Quintes



Connect with me on LinkedIn or Twitter

Monday, 15 May 2017

Azure IoT Hub connect error from node cannot read property 'write' of null

Azure IoT Hub connect error from node app - cannot read property 'write' of null in amqp libs


Quickly setting up an Azure IoT hub this evening and wiring up some node services to play with, and read the device-to-cloud messages had me stumped as I would get this error intermittently

  stream.write(buffer, callback);
        ^
TypeError: Cannot read property 'write' of null

Turns out it may be the connection string I was using

Connection String causing timeouts  


So I was defaulting to this format

HostName=somewhere.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=<yours>

This would cause the error above intermittently, and I wanted to resolve it.

Turns out you can use another connection string format:

Endpoint=sb://yourshere.servicebus.windows.net/;SharedAccessKeyName=iothubowner;SharedAccessKey=;yours;EntityPath=yourEntityPath;

To find these values, go into Azure, go to your IoT hub, Messaging, Endpoints and click on the Events endpoint below:


A properties window will appear.

The Event Hub-compatible name goes in the yourEntityPath value.

The Event Hub-compatible endpoint is where you would enter the Endpoint.

I found the problem and resolution here. I haven't encountered the error "Cannot read property 'write' of null" again.

IoT is way more fun than the old days when I used to send frames down the serial port, using c++, or getting values from a PLC or a weigh bridge. Probably even more fun than the Win SC API. But working with those devices is always good fun.

Cheers
Quintes

Connect with me on LinkedIn or Twitter

Thursday, 27 April 2017

Xubuntu 14.04 Samba setup for access by ubuntu and windows clients

Xubuntu 14.04 Samba setup for access by ubuntu and windows clients


Setting up a samba server locally was done as follows on ubuntu 14.04. On the server I had some errors with missing dependencies and had to perform some purges on samba packages to resolve them.

Reading this, this and this  helped.

Samba Server setup  


On the samba server, run the following:
sudo apt-get install samba samba-common system-config-samba gksu
I received errors that certain samba package dependencies could not be met, and searching for a fix led me to do this:

sudo apt-get clean
sudo apt-get autoremove
sudo apt-get update
sudo apt-get upgrade
sudo apt-get purge samba-common
sudo apt-get purge samba-libs
On xubuntu, could not find the samba config GUI from the menu, turns out I had to run it like this:

gksu system-config-samba

At this point in time I configured the share and user. 

Samba Client (linux)


On the first client, an ubuntu machine, I ran the following to get configured

sudo apt-get install samba cifs-utils

Create a credentials file so that the user and password is not littered everywhere

sudo nano /etc/samba/user
Add these:
username=samba_user
password=samba_user_password 

Set permissions to ro:

sudo chmod 0400 /etc/samba/user
Then edit /etc/fstab, add this entry as a new line to mount on boot:

sudo cp /etc/fstab /etc/fstab.bak1
sudo /etc/fstab

Add this line:

//samba-server/share  /media/share  cifs  credentials=/etc/samba/user,noexec  0 0
Either reboot or mount and you should be in:
sudo mount /media/share/

Samba Client (Windows)


Easy really, just open explorer and go to the network share \\samba-server\share\, enter the samba user and password and you're in.

@quintes