<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sedky Abou-Shamalah</title>
    <description>The latest articles on DEV Community by Sedky Abou-Shamalah (@sedkis).</description>
    <link>https://dev.to/sedkis</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F520344%2Fc3c3b1ed-e323-4bd1-8881-ffc3f1e73734.png</url>
      <title>DEV Community: Sedky Abou-Shamalah</title>
      <link>https://dev.to/sedkis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sedkis"/>
    <language>en</language>
    <item>
      <title>
Convert REST to GraphQL With No-Code
</title>
      <dc:creator>Sedky Abou-Shamalah</dc:creator>
      <pubDate>Wed, 29 Dec 2021 19:15:21 +0000</pubDate>
      <link>https://dev.to/sedkis/convert-rest-to-graphql-with-no-code-36ap</link>
      <guid>https://dev.to/sedkis/convert-rest-to-graphql-with-no-code-36ap</guid>
      <description>&lt;p&gt;&lt;strong&gt;REST to GraphQL magic&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What would you do if you needed to turn three legacy REST services into one smart, secure and easy to manage data graph? And what would you then do with that graph? &lt;/p&gt;

&lt;p&gt;In this article, we’ll walk you through the magic of using Universal Data Graph (UDG) to combine multiple REST services into a single graph. How you then leverage that power is entirely up to you… &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Universal Data Graph in action&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine you have three different REST resources that you want to tie together into a single graph. In fact, don’t just imagine, work alongside this article using publicly available resources from &lt;a href="https://jsonplaceholder.typicode.com/" rel="noopener noreferrer"&gt;JSON Placeholder&lt;/a&gt; to see how easy it is. &lt;/p&gt;

&lt;p&gt;For the purposes of this process, we suggest using the Users resource, which returns a list of users: &lt;a href="https://jsonplaceholder.typicode.com/users" rel="noopener noreferrer"&gt;https://jsonplaceholder.typicode.com/users &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter an ID and you can see a single resource. For example: &lt;a href="https://jsonplaceholder.typicode.com/users/5/" rel="noopener noreferrer"&gt;https://jsonplaceholder.typicode.com/users/5/   &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An individual user can have posts, as you can see here: &lt;a href="https://jsonplaceholder.typicode.com/users/5/posts" rel="noopener noreferrer"&gt;https://jsonplaceholder.typicode.com/users/5/posts&lt;/a&gt; Enter the URL and you’ll see a long list of posts that belong to that individual user. &lt;/p&gt;

&lt;p&gt;The final level of this is that each post can have comments. So if you have a post with an ID of 41, you can look at &lt;a href="https://jsonplaceholder.typicode.com/comments?postid=41" rel="noopener noreferrer"&gt;https://jsonplaceholder.typicode.com/comments?postid=41&lt;/a&gt; to view them. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let the stitching begin&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What if, instead of making three different calls, you stitched those three resources together? That way, you could work with a single graph call instead. &lt;/p&gt;

&lt;p&gt;To do so, start with the &lt;a href="https://tyk.io/docs/tyk-dashboard/" rel="noopener noreferrer"&gt;Tyk Dashboard&lt;/a&gt; and add a new API. Call it ‘composed’ and check the ‘GraphQL’ and ‘Compose new GraphQL service’ options. Next, click ‘Configure API’ at the top right of the dashboard and select ‘Open (Keyless)*’ as your authentication mode. &lt;/p&gt;

&lt;p&gt;Save and then click into your API to start building the schema. Click on ‘Schema.’ You won’t need a mutation, so delete that and just keep the query. &lt;/p&gt;

&lt;p&gt;Next, add a new user type, entering the ID (ID), name (String), email (String) and username (String). There are more that you can add, but these are sufficient for demonstration purposes. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq7ufj893k5wmpoeixzst.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq7ufj893k5wmpoeixzst.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, change the default query into the user query, taking in ID (mark it with an exclamation mark to show its mandatory) and setting the type as a user. &lt;/p&gt;

&lt;p&gt;That’s it in the schema editor. Now switch over to ‘data sources’ and you’ll see your user query. Data sources are required, so click on the user query and then on ‘data source’ where you can toggle the ‘define data sources’ slider. &lt;/p&gt;

&lt;p&gt;You’ll have a couple of options when it comes to data source type. Click on ‘REST’ and enter the URL you used earlier: &lt;a href="https://jsonplaceholder.typicode.com/users/5/" rel="noopener noreferrer"&gt;https://jsonplaceholder.typicode.com/users/5/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, instead of the ‘5’ you can use Golang templating – &lt;code&gt;{{ }}&lt;/code&gt; – and ‘.arguments’ to access the arguments that are available in the data model. Enter ‘.id’ for the name of the argument that you made. So you should end up with a URL that reads:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://jsonplaceholder.typicode.com/users/{{ .arguments.id }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Choose &lt;code&gt;Get&lt;/code&gt; as the method and click ‘Update field’ at the bottom right. And that’s it. &lt;/p&gt;

&lt;p&gt;Time to play &lt;/p&gt;

&lt;p&gt;Now it’s time to head to the playground within the Tyk Dashboard and write your user query, asking for the ID, name and email. You’ll need to include a user ID, so opt for 5, in line with the example we’re working on.  &lt;/p&gt;

&lt;p&gt;Hit the play symbol. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftuaim9tp4knxgnqepl6z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftuaim9tp4knxgnqepl6z.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the GraphQL resolver has taken the graph query and resolved it into the REST call to the upstream with the ID of 5. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adding in the posts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, let’s tie in the posts. To see all the posts that belong to this user, head back to the schema and add in a new type, called post. Add in the user ID (ID), post ID (ID), title (String) and body (String). &lt;/p&gt;

&lt;p&gt;The user can now have a new type, so add posts to the user types (an array of type post). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhzekzeo9a7ujri3o26lu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhzekzeo9a7ujri3o26lu.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Head over to data sources again and you’ll see that the user has a new type: posts. You can now define this as a data source, so that your GraphQL resolver knows to make a REST call to this resource if you ask for a post. &lt;/p&gt;

&lt;p&gt;Click on ‘posts’ under the user type and, in the data model section, ensure that ‘Is List’ is checked. Now, under data sources, toggle the define data sources slider and use the predefined example that you built previously:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://jsonplaceholder.typicode.com/users/{{ .arguments.id }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, add the endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://jsonplaceholder.typicode.com/users/{{ .arguments.id }}/posts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, this data source doesn’t have an argument, so instead of arguments.id, you can use .object – that lets you use any of the fields that were resolved from this current data source. In this example that means you can use any of ID, name, email, username or posts. Using &lt;code&gt;.id&lt;/code&gt; will inject the user ID into the next call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://jsonplaceholder.typicode.com/users/{{ .object.id }}/posts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With me so far? Great. Click ‘Update field’ and go back to the playground. &lt;/p&gt;

&lt;p&gt;You can now add posts, including user ID, title and the ID of the posts, into your query. Hit play and you’ll see the results – all the posts that belong to user number 5, including their titles and post IDs. &lt;/p&gt;

&lt;p&gt;Next, you can use those post IDs for the next chain: comments. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adding in the comments&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each post can have a comment. You can see this takes an argument in the query parameter, as shown here with the post ID: &lt;a href="https://jsonplaceholder.typicode.com/comments?postid=41" rel="noopener noreferrer"&gt;https://jsonplaceholder.typicode.com/comments?postid=41&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To get the comments for any post ID, head back to your schema once more and add a new type: comment, along with post ID (ID), comment ID (ID), name (String), body (String) and email (String). &lt;/p&gt;

&lt;p&gt;Now you can modify your post type to include comments (an array of type comment). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6gqmj5h0irta2utuocp7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6gqmj5h0irta2utuocp7.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Head over to data sources again, open up &lt;code&gt;comments&lt;/code&gt; within the post type and toggle ‘define data sources’ in ‘data sources.’  &lt;/p&gt;

&lt;p&gt;Now, you want to make a REST call to &lt;code&gt;comments&lt;/code&gt; with a query parameter of &lt;code&gt;postid&lt;/code&gt; and using the ID field from the post data source, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://jsonplaceholder.typicode.com/comments?postid={{ .object.id }}/posts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update field once again and head over to the playground, where you can now add comments to your query, including the post ID, name, email and body. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0fz0ub5vpty4wgv6d8n0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0fz0ub5vpty4wgv6d8n0.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hit play and voilà – you can now see the comments for each post. &lt;/p&gt;

&lt;p&gt;And that’s it – that’s how easy it is to stitch three different REST resources together, combining them into a single graph. &lt;/p&gt;

&lt;p&gt;Now it’s your turn. Where will this newfound ability take you?&lt;/p&gt;

</description>
      <category>graphql</category>
    </item>
    <item>
      <title>Setting up AWS Appsync for unauthenticated users</title>
      <dc:creator>Sedky Abou-Shamalah</dc:creator>
      <pubDate>Tue, 02 Nov 2021 19:06:05 +0000</pubDate>
      <link>https://dev.to/sedkis/setting-up-aws-appsync-for-unauthenticated-users-1879</link>
      <guid>https://dev.to/sedkis/setting-up-aws-appsync-for-unauthenticated-users-1879</guid>
      <description>&lt;p&gt;Edit:&lt;br&gt;
Here's an updated version of this blog:&lt;br&gt;
&lt;a href="https://sedkodes.com/blog/aws-appsync-for-unauthenticated-users" rel="noopener noreferrer"&gt;https://sedkodes.com/blog/aws-appsync-for-unauthenticated-users&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This took me days to get the handle of, so here's to hoping I can save anybody else the trouble.&lt;/p&gt;

&lt;p&gt;so you want to expose some of your queries (but not all!) to public users, so that users can use/interact with your app before having to sign up.  Makes sense!!&lt;/p&gt;

&lt;p&gt;Well, it's a royal PITA.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Set your Appsync API to be protected by IAM&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuy4vak1yuabytgztp6yp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuy4vak1yuabytgztp6yp.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a Cognito identity pool, and create a role for unauthenticated users:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fboka9y85ivyu0xp65b3u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fboka9y85ivyu0xp65b3u.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For the unauthenticated role, specifically assign the fields/types you want.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you'd like to be confused by AWS' documentation of how to do this, start &lt;a href="https://docs.aws.amazon.com/service-authorization/latest/reference/list_awsappsync.html#awsappsync-field" rel="noopener noreferrer"&gt;here&lt;/a&gt;, or &lt;a href="https://docs.aws.amazon.com/appsync/latest/devguide/security_iam_service-with-iam.html#security_iam_service-with-iam-id-based-policies" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Alternatively, you can copy this template where I give access to two subscriptions only:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "appsync:GraphQL",
            "Resource": [
                "arn:aws:appsync:*:*:apis/*/types/*/fields/onCreateOrders",
                "arn:aws:appsync:*:*:apis/*/types/*/fields/onUpdateOrders"
            ]
        }
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, in our JS code, I use the Amplify SDK, so here's how I configure that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const config = awsRealtimeConfig: {
        aws_appsync_graphqlEndpoint: "https://&amp;lt;graphql-id&amp;gt;.appsync-api.&amp;lt;aws-region&amp;gt;.amazonaws.com/graphql",
        aws_appsync_region: "&amp;lt;region&amp;gt;",
        aws_appsync_authenticationType: 'AWS_IAM',
        Auth: {
            identityPoolId: 'us-east-2:pool-id-here',
            region: 'us-east-2',
        }
    },

Amplify.configure(config)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>aws</category>
      <category>appsync</category>
      <category>security</category>
    </item>
    <item>
      <title>Let's stop using JWTs client side</title>
      <dc:creator>Sedky Abou-Shamalah</dc:creator>
      <pubDate>Tue, 08 Dec 2020 16:11:28 +0000</pubDate>
      <link>https://dev.to/sedkis/let-s-stop-using-jwts-client-side-22cp</link>
      <guid>https://dev.to/sedkis/let-s-stop-using-jwts-client-side-22cp</guid>
      <description>&lt;p&gt;Here's an updated version of this blog:&lt;br&gt;
&lt;a href="https://sedkodes.com/blog/lets-stop-using-jwts"&gt;https://sedkodes.com/blog/lets-stop-using-jwts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Split Token Flow: A solution to the security problem of the JWT&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;OAuth2, OIDC, and their foundation, the JWT, has been an industry standard for many years, with no sign of slowing down.&lt;/p&gt;

&lt;p&gt;The problem with the JWT is the inherent leakiness. There is a massive debate amongst the community - where some consider JWT for auth as insecure as it leaks information (by b64 decoding the body), others argue that you shouldn't put sensitive info in there at all.&lt;/p&gt;

&lt;p&gt;So that’s where the split token flow comes in.  This flow suggests to use just the signature of the JWT access token on the client side, and storing the header and claims of the JWT server side.  Thus, the split token flow satisfies both camps - we get the flexibility of JWTs by being able to store session information in JWT claims, and we get the security of an Opaque access token - because we don't actually expose the entire token, only the signature. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How can this be achieved with an API Gateway?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Full Disclosure, I am an employee of Tyk.  The following guide contains screenshots of Tyk Pro product.  However, all of this functionality is completely free to implement using the OSS Gateway as well.  In fact, you can browse to &lt;a href="https://github.com/sedkis/split-token-tyk"&gt;this repository&lt;/a&gt; which will provide a step-by-step guide to doing the rest with the OSS Tyk Gateway.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;First, let’s take an example of client credentials flow, where we exchange a client id and secret for a JWT access token that we can use to access our APIs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl -X POST -H 'Content-Type: application/x-www-form-urlencoded' https://keycloak-host/auth/realms/tyk/protocol/openid-connect/token \
-d grant_type=client_credentials \
-d client_id=efd952c8-df3a-4cf5-98e6-868133839433 \
-d client_secret=0ede3532-f042-4120-bece-225e55a4a2d6 \
&amp;gt; -s | jq
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJlbWFpbCI6ImhlbGxvQHdvcmxkLmNvbSJ9.EwIaRgq4go4R2M2z7AADywZ2ToxG4gDMoG4SQ1X3GJ0",
  "expires_in": 300,
  "token_type": "bearer",
  "not-before-policy": 0,
  "scope": "email profile"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So here we get a JWT access token back:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJlbWFpbCI6ImhlbGxvQHdvcmxkLmNvbSJ9.EwIaRgq4go4R2M2z7AADywZ2ToxG4gDMoG4SQ1X3GJ0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Header&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Body&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJlbWFpbCI6ImhlbGxvQHdvcmxkLmNvbSJ9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Signature&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EwIaRgq4go4R2M2z7AADywZ2ToxG4gDMoG4SQ1X3GJ0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can plug that into jwt.io and see the decoded payload:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Px_q3qng--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/d2f51pmalzv35tafmuei.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Px_q3qng--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/d2f51pmalzv35tafmuei.png" alt="Alt Text" width="880" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clearly, the access token can contain sensitive information that we don’t want to leak.  &lt;/p&gt;

&lt;p&gt;The API Gateway is perfectly positioned to act as a broker between the client and the authorization server.  &lt;/p&gt;

&lt;p&gt;It can intercept requests from clients, receive a client id and secret, and exchange that for an access token with the authorization server.  In this broker position, the API gateway can break apart the JWT, and return only the signature portion of the real JWT access token back to the client. We then store the rest of the JWT as metadata.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting it Up&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Inside Tyk, let’s create a virtual endpoint or API, listening on the path "/auth/token". &lt;/p&gt;

&lt;p&gt;Let’s take a look at some sample code for the Virtual Endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function login(request, session, config) {
    var credentials = request.Body.split("&amp;amp;")
        .map(function(item, index) {
            return item.split("=");
      }).reduce(function(p, c) {
             p[c[0]] = c[1];
             return p;
      }, {});

    var newRequest = {
      "Headers": {"Content-Type": "application/x-www-form-urlencoded"},
      "Method": "POST",
      "FormData": {
          grant_type: credentials.grant_type,
          client_id: credentials.client_id,
          client_secret: credentials.client_secret
      },
      "Domain": "https://keycloak-host",
      "resource": "/auth/realms/tyk/protocol/openid-connect/token",
    };

    var response = TykMakeHttpRequest(JSON.stringify(newRequest));
    var usableResponse = JSON.parse(response);

    if (usableResponse.Code !== 200) {
      return TykJsResponse({
        Body: usableResponse.Body,
        Code: usableResponse.Code
      }, session.meta_data)
    }

    var bodyObj = JSON.parse(usableResponse.Body);
    var accessTokenComplete = bodyObj.access_token;
    var signature = accessTokenComplete.split(".")[2];

    log("completeAccessToken: " + accessTokenComplete);

    // create key inside Tyk
    createKeyInsideTyk(signature, bodyObj)

    // override signature
    bodyObj.access_token = signature;
    delete bodyObj.refresh_expires_in;
    delete bodyObj.refresh_token;
    delete bodyObj.foo;

  var responseObject = {
    Body: JSON.stringify(bodyObj),
    Code: usableResponse.Code
  }
  return TykJsResponse(responseObject, session.meta_data)
}

function createKeyInsideTyk(customKey, meta) {
    // TODO: this needs to be a bit more dynamic. e.g. work out the policy id &amp;amp; API ID etc... based on the metadata
    var accessRights = {
        "c399587af48441d17bc5700339aa34fa": {
            "api_name": "Test API",
            "api_id": "c399587af48441d17bc5700339aa34fa",
            "versions": [
                "Default"
            ]
        }
    }

    log("meta: " + JSON.stringify(meta));

    var keyRequestBody = keyRequestTemplate;
    keyRequestBody.access_rights = accessRights;

    var newRequest = {
      "Headers": {"Content-Type": "application/json", "Authorization": "Bearer a4fcbde85a3c477d424922990eb16e01"},
      "Method": "POST",
      "Body": JSON.stringify(keyRequestBody),
      "Domain": "http://localhost:3000",
      "resource": "/api/keys/" + customKey,
    };

    var response = TykMakeHttpRequest(JSON.stringify(newRequest));
    log("createkeyintykres: " + response);
}

var keyRequestTemplate = {
    "apply_policies": [],
    "org_id" : "5d67b96d767e02015ea84a6f",
    "expires": 0,
    "allowance": 0,
    "per": 0,
    "quota_max": 0,
    "rate": 0,
    "access_rights": {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code does the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Virtual Endpoint receives a request containing a client ID + Secret&lt;/li&gt;
&lt;li&gt;It forwards the request to the authorization server and receives the access JWT token&lt;/li&gt;
&lt;li&gt;It splits the access token, creating an opaque key in Tyk, which is the signature of the JWT access token&lt;/li&gt;
&lt;li&gt;It adds the Header and the Body of the access token as metadata to that opaque key so that we can look it up on subsequent requests&lt;/li&gt;
&lt;li&gt;It returns the opaque key (signature) to the client where they can use it to access APIs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At the beginning, from the client perspective:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl http://tyk-gw:8080/auth/token -X POST -H 'Content-Type: application/x-www-form-urlencoded' -d client_id=efd952c8-df3a-4cf5-98e6-868133839433 -d client_secret=0ede3532-f042-4120-bece-225e55a4a2d6 -d grant_type=client_credentials

{"access_token":"MEwIaRgq4go4R2M2z7AADywZ2ToxG4gDMoG4SQ1X3GJ0","expires_in":300,"not-before-policy":0,"scope":"email profile","session_state":"fb8754d1-d518-40e8-a84f-85347a0639c8","token_type":"bearer"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's look up the opaque token&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dDtd1gzg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/iwis49iwgelv2ba011x4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dDtd1gzg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/iwis49iwgelv2ba011x4.png" alt="Alt Text" width="880" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the key’s meta data&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Gi39ztIZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/itt5cl5hxclz0rdkf6qn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Gi39ztIZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/itt5cl5hxclz0rdkf6qn.png" alt="Alt Text" width="880" height="259"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s test our API key against the API we added to the access rights in the Create Key payload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl localhost:8080/basic-protected-api/get -H "Authorization: MEw….GJ0"
{
  "args": {},
  "headers": {
    "Accept": "*/*",
    "Accept-Encoding": "gzip",
    "Authorization": "MEwIaRgq4go4R2M2z7AADywZ2ToxG4gDMoG4SQ1X3GJ0",
    "Host": "httpbin",
    "User-Agent": "curl/7.64.1"
  },
  "origin": "192.168.80.1",
  "url": "http://httpbin/get"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tyk validates the opaque token and allows access to the API. &lt;/p&gt;

&lt;p&gt;In Tyk, let's reconstruct the full JWT and safely pass it to our upstream API.&lt;/p&gt;

&lt;p&gt;In the previous step, we stored the full JWT in the session token’s metadata inside Tyk.  We can extract the JWT from the request’s session metadata and then inject it into the requests headers.&lt;/p&gt;

&lt;p&gt;Let’s configure the API to inject a global header like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--69dSQ-f1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gmgz10c2b79stcf1e9ch.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--69dSQ-f1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gmgz10c2b79stcf1e9ch.png" alt="Alt Text" width="880" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s try the API call again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl localhost:8080/basic-protected-api/get -H "Authorization: MEw….GJ0"
{
  "args": {},
  "headers": {
    "Accept": "*/*",
    "Accept-Encoding": "gzip",
    "Authorization": "Bearer eyJh...1X3GJ0",
    "Host": "httpbin",
    "User-Agent": "curl/7.64.1"
  },
  "origin": "192.168.80.1",
  "url": "http://httpbin/get"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tada!&lt;br&gt;
As you can see, even though we only sent an opaque token in the request, Tyk injected the rest of the JWT where our upstream can now use it to perform business logic.&lt;/p&gt;

&lt;p&gt;If you have any questions or want to start a conversation, I encourage you to email me at &lt;a href="//mailto:sedky@tyk.io"&gt;sedky@tyk.io&lt;/a&gt; with any questions.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>OSX Terminal Must Haves</title>
      <dc:creator>Sedky Abou-Shamalah</dc:creator>
      <pubDate>Wed, 25 Nov 2020 03:20:05 +0000</pubDate>
      <link>https://dev.to/sedkis/osx-terminal-must-haves-1li</link>
      <guid>https://dev.to/sedkis/osx-terminal-must-haves-1li</guid>
      <description>&lt;p&gt;Having a really efficient CMD line is awesome. It can save you a lot of time. It’s good to take the time to set up a terminal that is intuitive and customized to you and your workflow.&lt;/p&gt;

&lt;p&gt;With the right software, you can do things like autocomplete your GIT commands, Docker commands and more. This alone is worth it. But also, you get &lt;strong&gt;DARK MODE!&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Must Haves
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://iterm2.com/"&gt;iTerm2&lt;/a&gt; — Replace and make this your default Terminal NOW. check out all the &lt;a href="https://iterm2.com/features.html"&gt;FEATURES!&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/ohmyzsh/ohmyzsh"&gt;Oh My Zsh&lt;/a&gt; — Steroids for your terminal. This gives us all the cool shit we need, like Autocomplete features, custom themes, and WAY MORE.&lt;br&gt;
Go and install these two.&lt;/p&gt;

&lt;h4&gt;
  
  
  Docker/Git Auto complete
&lt;/h4&gt;

&lt;p&gt;With iTerm2 and Oh My Zsh downloaded and installed, let’s add some plugins. Open your zsh profile, located in ~./.zshrc&lt;/p&gt;

&lt;p&gt;edit the plugins section:&lt;/p&gt;

&lt;p&gt;plugins=(&lt;br&gt;
 git&lt;br&gt;
 osx&lt;br&gt;
 docker&lt;br&gt;
 docker-compose&lt;br&gt;
)&lt;br&gt;
Now we get sweet autofill features. Here’s a list of hundreds of others:&lt;/p&gt;

&lt;p&gt;such as minikube, node, and more!&lt;/p&gt;

&lt;h4&gt;
  
  
  Quick line jumps!
&lt;/h4&gt;

&lt;p&gt;Are you a peasant that holds -&amp;gt; until they reach the end of the line? Well no more you aren’t!&lt;/p&gt;

&lt;p&gt;You can setup iTerm2 to let you jump around the current line. Find the basics here to get you started:iTerm 2: How to set keyboard shortcuts to jump to beginning/end of line?I can see that Ctrl+ left/ right jumps to the beginning/end of line. How to change this to Cmd+ left/ right arrow? In…stackoverflow.com&lt;/p&gt;

&lt;h4&gt;
  
  
  Quick directory jumps!
&lt;/h4&gt;

&lt;p&gt;A command line tool that helps you jump around to different directories using partial strings. Example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/agkozak/zsh-z"&gt;Click here for the plugin link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have more, email me or comment ! Thanks!&lt;/p&gt;

&lt;p&gt;Props to my buddy &lt;a href="https://www.linkedin.com/in/rob-davis/"&gt;Rob Davis&lt;/a&gt; who shared these tips with me&lt;/p&gt;

</description>
      <category>devops</category>
    </item>
    <item>
      <title>Firebase SSO?</title>
      <dc:creator>Sedky Abou-Shamalah</dc:creator>
      <pubDate>Wed, 25 Nov 2020 03:16:43 +0000</pubDate>
      <link>https://dev.to/sedkis/firebase-sso-3i89</link>
      <guid>https://dev.to/sedkis/firebase-sso-3i89</guid>
      <description>&lt;p&gt;Edit: I've figured out how to implement this with a middle proxy layer, you can watch it on &lt;a href="https://www.youtube.com/watch?v=QJC3bb45UgE&amp;amp;ab_channel=SedkyAbou-Shamalah"&gt;YouTube&lt;/a&gt;.  I'm leaving the rest of the article unedited as it's still quite accurate.&lt;/p&gt;

&lt;p&gt;If you're here because you are trying to figure out how to use Firebase for SSO purposes, let me be the first to tell you:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Firebase Authentication WAS NOT DESIGNED FOR SSO.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Turns out that a Federated IdP is not the same thing as an IdP. Who would’ve thunk it ?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HOWEVER&lt;/strong&gt;.  Can you build your own flows around it? Probably!&lt;/p&gt;

&lt;p&gt;If you’ve worked with Firebase, you know it’s an amazing suite of products that allows you to rapidly prototype and build extremely scalable websites.&lt;/p&gt;

&lt;p&gt;However, if you’re wondering if you can use Firebase Authentication for SSO, well, you can’t. Firebase Authentication is a federated IdP management system. It is the “client” in the OIDC/OAuth flow and for that reason, you can’t be a client in a client relationship.&lt;/p&gt;

&lt;p&gt;There are tools that exist for this sort of thing, such as OneLogin, which are true SSO solutions. Firebase authentication is a good authentication tool for your websites, but it will not solve your SSO problems outside of that.&lt;/p&gt;

&lt;p&gt;Interestingly enough, you can bypass Firebase and then use one of the underlying IdPs to SSO into platforms. For example, instead of using Google Login through Firebase, you could just use Google Login. Same with Facebook Login. These are true IdP solutions which implement OIDC and OAuth2 frameworks correctly. But when Firebase is in the middle, you cannot use them except to log into a web app you are building.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>devops</category>
      <category>cloud</category>
    </item>
  </channel>
</rss>
