<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Gaurav Swarankar on Medium]]></title>
        <description><![CDATA[Stories by Gaurav Swarankar on Medium]]></description>
        <link>https://medium.com/@gauravswarankar?source=rss-338d813a8d58------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*OhDruVk_dBhbaE4AhdOZCg.png</url>
            <title>Stories by Gaurav Swarankar on Medium</title>
            <link>https://medium.com/@gauravswarankar?source=rss-338d813a8d58------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 07:57:41 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@gauravswarankar/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Concurrency in Dart (Part — 1)]]></title>
            <link>https://medium.com/@gauravswarankar/concurrency-in-dart-part-1-519c061026a0?source=rss-338d813a8d58------2</link>
            <guid isPermaLink="false">https://medium.com/p/519c061026a0</guid>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[concurrency]]></category>
            <category><![CDATA[dart]]></category>
            <category><![CDATA[concurrent-programming]]></category>
            <dc:creator><![CDATA[Gaurav Swarankar]]></dc:creator>
            <pubDate>Tue, 18 Aug 2026 10:13:34 GMT</pubDate>
            <atom:updated>2026-08-18T10:13:34.292Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*mRxh5WY1t9XvYbfV.jpg" /></figure><p>Running/handling multiple tasks within a program, where tasks can make progress without unnecessarily waiting for each other. Dart concurrency is not the same as “multiple Dart instructions running at exactly the same time.”</p><p>If you execute tasks <strong>strictly one by one</strong>, that’s <strong>Sequential Execution</strong>, not concurrency.</p><p>It does <strong>not necessarily mean</strong> that everything runs at the exact same moment.</p><pre>Task A → API request<br>Task B → Database request<br>Task C → File operation</pre><pre>A → wait → finish<br>B → wait → finish<br>C → wait → finish</pre><p>we can allow them to overlap:</p><pre>A ──────────────────→ finish<br>B ───────────→ finish<br>C ────────→ finish</pre><p>That’s concurrency.</p><h3>Why do we need Concurrency?</h3><p>Imagine your Flutter app needs to load:</p><ol><li>User profile</li><li>User orders</li><li>Notifications</li></ol><p>Each API takes around 2 seconds.</p><p><strong>Sequential approach:</strong></p><pre>final profile = await getProfile();<br>final orders = await getOrders();<br>final notifications = await getNotifications();</pre><p>Suppose each API takes 2 seconds:</p><p>Timeline:</p><pre>0s                2s                4s                6s<br>│─────────────────│─────────────────│─────────────────│<br>   getProfile         getOrders          notifications<br>   ████████████       ████████████       ████████████</pre><p>Total ≈ <strong>6 seconds. </strong>But these APIs are independent. So we can start them together.</p><pre>getProfile()<br>   ↓<br>START<br>   ↓<br>await → WAIT 2 sec<br>   ↓<br>profile received<br>   ↓<br>getOrders()          ← only NOW it starts<br>   ↓<br>await → WAIT 2 sec<br>   ↓<br>orders received<br>   ↓<br>getNotifications()   ← only NOW it starts</pre><p><strong>Concurrent approach:</strong></p><pre>final profileFuture = getProfile();<br>final ordersFuture = getOrders();<br>final notificationsFuture = getNotifications();<br><br>final profile = await profileFuture;<br>final orders = await ordersFuture;<br>final notifications = await notificationsFuture;</pre><p>Now Look carefully at the first three lines:</p><pre>final profileFuture = getProfile();<br>final ordersFuture = getOrders();<br>final notificationsFuture = getNotifications();</pre><p>There is <strong>NO </strong><strong>await here</strong>. So all three operations are started immediately:</p><pre>0s<br>│<br>├── getProfile()        ████████████ → 2s<br>│<br>├── getOrders()         ████████████ → 2s<br>│<br>└── getNotifications()  ████████████ → 2s</pre><p>Only <strong>after starting all three</strong>, we wait for their results:</p><pre>final profile = await profileFuture;<br>final orders = await ordersFuture;<br>final notifications = await notificationsFuture;</pre><p>So total ≈ <strong>2 seconds</strong>, not 6. This is a very practical example of concurrency. In Dart, asynchronous operations commonly return a Future.</p><p>Think of a Future as:</p><blockquote><strong><em>“I don’t have the result right now, but I’ll give it to you later.”</em></strong></blockquote><h3><strong>What does </strong><strong>await do?</strong></h3><pre>final user = await fetchUser();</pre><p>await means:</p><blockquote><em>“Wait for this Future’s result before continuing this particular async function.” </em><strong>It does NOT mean that the entire Dart program freezes. </strong>That’s a very common beginner misunderstanding.</blockquote><h3>Sequential vs Concurrent</h3><p>Sequential:</p><pre>final a = await taskA();<br>final b = await taskB();<br>final c = await taskC();</pre><pre>Task A<br>████████<br><br>        Task B<br>        ████████<br><br>                Task C<br>                ████████</pre><pre>A = 2 sec<br>B = 3 sec<br>C = 1 sec</pre><p>So Total, 2 + 3 + 1 = 6 seconds</p><h3>Concurrent:</h3><pre>final futureA = taskA();<br>final futureB = taskB();<br>final futureC = taskC();<br><br>final a = await futureA;<br>final b = await futureB;<br>final c = await futureC;</pre><pre>Task A<br>████████████<br><br>Task B<br>██████████████████<br><br>Task C<br>██████</pre><p>All three are started before we wait for their results.</p><p>Total: max(2, 3, 1) = 3 seconds</p><h3>Future.wait()</h3><p>specifically useful when you have multiple independent Futures and need all their results.</p><pre>final results = await Future.wait([<br>  taskA(),<br>  taskB(),<br>  taskC(),<br>]);</pre><pre>             ┌── Task A ──┐<br>             │             │<br>Future.wait ─┼── Task B ──┼──→ All completed<br>             │             │<br>             └── Task C ──┘</pre><h3>Very important: Future.wait doesn&#39;t magically make code faster</h3><p>Suppose:</p><pre>Future&lt;int&gt; taskA() async {<br>  await Future.delayed(Duration(seconds: 2));<br>  return 10;<br>}<br><br>Future&lt;int&gt; taskB() async {<br>  await Future.delayed(Duration(seconds: 3));<br>  return 20;<br>}</pre><p>This:</p><pre>await Future.wait([<br>  taskA(),<br>  taskB(),<br>]);</pre><p>doesn’t make either operation itself faster.</p><p>Instead:</p><pre>Sequential:<br><br>A ████████ 2 sec<br>         B ████████████ 3 sec<br>Total = 5 sec<br><br><br>Concurrent:<br><br>A ████████<br>B ████████████<br>Total = 3 sec</pre><h3>What is a Dart Isolate?</h3><p>An <strong>isolate</strong> is an independent Dart execution environment.</p><p>In a typical Flutter app, we mainly work with one isolate:</p><pre>Flutter App<br>    │<br>    ▼<br>Main Dart Isolate<br>    │<br>    ├── Dart code<br>    ├── Event Loop<br>    ├── Microtask Queue<br>    └── Event Queue</pre><p>One isolate normally executes one Dart operation at a time.</p><pre>print(&quot;A&quot;);<br>print(&quot;B&quot;);<br>print(&quot;C&quot;);</pre><p>We didn’t get A and B and C simultaneously. Instead:</p><pre>A<br>↓<br>B<br>↓<br>C</pre><p>The Dart isolate executes them sequentially.</p><h3>How does asynchronous code work?</h3><pre>Future&lt;void&gt; loadData() async {<br>  print(&quot;Start&quot;);<br><br>  final user = await fetchUser();<br><br>  print(user);<br>  print(&quot;End&quot;);<br>}</pre><pre>Future&lt;String&gt; fetchUser() async {<br>  await Future.delayed(Duration(seconds: 2));<br>  return &quot;Gaurav&quot;;<br>}</pre><p>We might initially think:</p><pre>Start<br>   ↓<br>wait 2 seconds<br>   ↓<br>Gaurav<br>   ↓<br>End</pre><p>And that’s logically correct from the function’s perspective. But internally, Dart doesn’t simply freeze the entire isolate for 2 seconds. This is the important part.</p><h3>What does await actually mean?</h3><p>When Dart reaches:</p><pre>final user = await fetchUser();</pre><p>Dart essentially says:</p><blockquote><em>“I need the result of </em><em>fetchUser(), but that result isn&#39;t ready yet. I&#39;ll pause this async function and allow other work to execute.&quot;</em></blockquote><pre>loadData()<br>   │<br>   ├── print(&quot;Start&quot;)<br>   │<br>   └── await fetchUser()<br>             │<br>             └── Future not completed</pre><p>At this point, loadData() is <strong>suspended</strong>. But the isolate itself is <strong>not necessarily blocked</strong>. That’s a huge distinction. await pauses the async function, not the entire Dart isolate.</p><p>Dart remembers Continue from here when fetchUser completes.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=519c061026a0" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Async widgets Future Builder (Part -1)]]></title>
            <link>https://medium.com/@gauravswarankar/async-widgets-future-builder-part-1-0dcb56b1a424?source=rss-338d813a8d58------2</link>
            <guid isPermaLink="false">https://medium.com/p/0dcb56b1a424</guid>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[dart]]></category>
            <category><![CDATA[flutter-ui]]></category>
            <category><![CDATA[flutter-app-development]]></category>
            <category><![CDATA[flutter-widget]]></category>
            <dc:creator><![CDATA[Gaurav Swarankar]]></dc:creator>
            <pubDate>Tue, 21 Jul 2026 08:33:49 GMT</pubDate>
            <atom:updated>2026-07-21T08:33:49.287Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/828/0*93UqOmwsYkCvAV4T.jpeg" /></figure><p>Imagine your app needs data that is <strong>not immediately available</strong>.</p><ul><li>Fetch user profile from server</li><li>Read data from SQLite</li><li>Load SharedPreferences</li><li>Read a JSON file</li><li>Authenticate user</li><li>Download an image</li></ul><pre>App starts<br>      │<br>      ▼<br>Request data<br>      │<br>      ▼<br>Waiting...<br>      │<br>      ▼<br>Data arrives<br>      │<br>      ▼<br>Show UI</pre><p>Flutter needs a widget that can automatically update the UI when that work finishes. That’s exactly what <strong>FutureBuilder</strong> does.</p><blockquote><strong><em>FutureBuilder listens to a Future and rebuilds the UI whenever the Future’s state changes.</em></strong></blockquote><h3>What is a Future?</h3><p>Before learning FutureBuilder, students must understand Future. A <strong>Future</strong> represents <strong>a value that will be available later</strong>. Think of ordering food online.</p><pre>Restaurant<br><br>You order Pizza<br>      │<br>      ▼<br>Cooking<br>      │<br>      ▼<br>Delivery<br>      │<br>      ▼<br>You receive Pizza</pre><p>While the pizza is cooking, you don’t have it. Exactly the same with Future.</p><pre>Future&lt;User&gt;<br>↓<br>Waiting<br>↓<br>User object arrives later</pre><p>Example:</p><pre>Future&lt;String&gt; fetchName() async {<br>  await Future.delayed(Duration(seconds: 3));<br>  return &quot;Gaurav&quot;;<br>}</pre><p>Immediately after calling:</p><pre>fetchName();</pre><p>You <strong>don’t have:</strong></p><pre>&quot;Gaurav&quot;</pre><p>You only have</p><pre>Future&lt;String&gt;</pre><p>Three seconds later:</p><pre>Future&lt;String&gt;<br>↓<br>&quot;Gaurav&quot;</pre><p><strong>Why can’t we simply do this?</strong></p><p>Many beginners try:</p><pre>String name = fetchName();</pre><p>Flutter says</p><pre>A value of type Future&lt;String&gt;<br>can&#39;t be assigned to String</pre><p>Because:</p><pre>Future&lt;String&gt;<br>≠<br>String</pre><p>It is like</p><pre>Receipt<br>≠<br>Pizza</pre><p>The receipt only promises you’ll get pizza later. Without FutureBuilder Suppose you want to show user data.</p><p>Without FutureBuilder</p><pre>Screen opens<br>↓<br>Call API<br>↓<br>Show loading<br>↓<br>Wait<br>↓<br>Receive data<br>↓<br>setState()<br>↓<br>Hide loading<br>↓<br>Display data</pre><p>You write lots of code.</p><pre>bool loading = true;<br>String name = &quot;&quot;;<br>void loadUser() async {<br>  name = await fetchName();<br>  loading = false;<br>  setState(() {});<br>}</pre><p>Inside build:</p><pre>if(loading){<br>   return CircularProgressIndicator();<br>}else{<br>   return Text(name);<br>}</pre><p>Works But FutureBuilder does this automatically. FutureBuilder handles everything Instead of:</p><pre>loading variable<br>+<br>setState()<br>+<br>error handling<br>+<br>success handling</pre><p>You simply write:</p><pre>FutureBuilder()</pre><p>Basic Syntax:</p><pre>FutureBuilder&lt;String&gt;(<br>  future: fetchName(),<br>  builder: (context, snapshot) {},<br>)</pre><p>There are only two important properties.</p><pre>future<br><br>builder</pre><h3>future</h3><p>The async task.</p><pre>future: fetchName()</pre><pre>future: getProducts()</pre><pre>future: loadUser()</pre><h3>builder</h3><p>Builder receives an object called</p><pre>AsyncSnapshot</pre><pre>builder: (context, snapshot) {}</pre><p>Everything about the Future is inside snapshot.</p><h3>What is AsyncSnapshot?</h3><p>Think of it as a <strong>status report</strong>.</p><pre>Future<br>↓<br>Snapshot<br><br>contains<br>• Current State<br>• Data<br>• Error</pre><pre>AsyncSnapshot<br>------------------------<br>ConnectionState<br>Data<br>Error<br>StackTrace<br>------------------------</pre><h3>snapshot.connectionState</h3><p>This tells <strong>where the Future currently is</strong>. Possible values:</p><pre>none<br>waiting<br>active<br>done</pre><p>For FutureBuilder you’ll mostly use:</p><pre>waiting<br>done</pre><h3>ConnectionState.none</h3><p>No Future is attached.</p><pre>FutureBuilder<br>↓<br>future = null</pre><h3>ConnectionState.waiting</h3><p>The Future is still running.</p><pre>API Call<br>↓<br>Waiting...<br>↓<br>No data yet</pre><p>Usually show</p><pre>CircularProgressIndicator()</pre><h3>ConnectionState.done</h3><p>Future finished. Now either Success or Failed</p><h3>snapshot.hasData</h3><p>Returns if data arrived.</p><pre>API<br>↓<br>User<br>↓<br>snapshot.hasData == true</pre><h3>snapshot.data</h3><p>Actual result.</p><pre>Text(snapshot.data!)</pre><h3>snapshot.hasError</h3><p>If something failed.</p><pre>Internet disconnected<br>↓<br>API failed<br>↓<br>snapshot.hasError == true</pre><h3>snapshot.error</h3><p>Actual error.</p><pre>Text(snapshot.error.toString())</pre><p>Complete Flow:</p><pre>Future Starts<br>↓<br>ConnectionState.waiting<br>↓<br>Loading Spinner<br>↓<br>Future Completes<br>↓<br>ConnectionState.done<br>↓<br>Success ?<br>↓<br>Yes<br>↓<br>snapshot.data<br>↓<br>Show Data</pre><p>or</p><pre>Future Starts<br>↓<br>Waiting<br>↓<br>Done<br>↓<br>Failed<br>↓<br>snapshot.error<br>↓<br>Show Error</pre><h3>Why should we NOT create the Future inside build()?</h3><p>This is one of the most common beginner mistakes.</p><pre>Widget build(BuildContext context) {<br>  return FutureBuilder(<br>    future: fetchName(),<br>    builder: ...<br>  );<br>}</pre><p>Why is it a problem?</p><p>The build() method can run many times:</p><ul><li>The keyboard opens.</li><li>The device rotates.</li><li>The parent widget rebuilds.</li><li>setState() is called anywhere that affects this widget.</li></ul><h3>Correct way</h3><p>Create the Future once in initState() and reuse it.</p><pre>class _HomeState extends State&lt;Home&gt; {<br><br>  late Future&lt;String&gt; futureName;<br><br>  @override<br>  void initState() {<br>    super.initState();<br>    futureName = fetchName();<br>  }<br><br>  @override<br>  Widget build(BuildContext context) {<br>    return FutureBuilder&lt;String&gt;(<br>      future: futureName,<br>      builder: (context, snapshot) {<br>        // Build UI<br>      },<br>    );<br>  }<br>}</pre><p>Now the flow becomes:</p><pre>initState()<br><br>↓<br><br>fetchName()<br><br>↓<br><br>Future stored<br><br>↓<br><br>build()<br><br>↓<br><br>FutureBuilder uses same Future<br><br>↓<br><br>Parent rebuilds<br><br>↓<br><br>build()<br><br>↓<br><br>Same Future reused<br><br>↓<br><br>No duplicate API call</pre><h3>What is initialData?</h3><p>Suppose you don’t want to display null while waiting. You can provide an initial value.</p><pre>FutureBuilder&lt;String&gt;(<br>  future: fetchName(),<br>  initialData: &quot;Loading user...&quot;,<br>  builder: (context, snapshot) {<br>    return Text(snapshot.data!);<br>  },<br>)</pre><p>During the waiting state, snapshot.data is &quot;Loading user...&quot;. After the Future completes, it becomes the real value (for example, &quot;Gaurav&quot;).</p><h3>FutureBuilder vs StreamBuilder</h3><pre>| Feature           | FutureBuilder             | StreamBuilder                                  |<br>| ----------------- | ------------------------- | ---------------------------------------------- |<br>| Data count        | One result                | Multiple results                               |<br>| Updates           | Once                      | Continuously                                   |<br>| Example           | API call, database read   | Chat messages, sensor data, Firebase listeners |<br>| Connection states | Mainly `waiting` → `done` | `waiting` → `active` → `done`                  |</pre><p>Think of them like this:</p><ul><li><strong>FutureBuilder</strong>: “Tell me once when you’re finished.”</li><li><strong>StreamBuilder</strong>: “Keep telling me whenever something changes.”</li></ul><h3>Real-world examples of FutureBuilder</h3><pre>| Scenario          | Future                                 <br>| ----------------- | -------------------------------------- <br>| Login             | Authenticate the user                  <br>| Splash screen     | Check if the user is already logged in <br>| E-commerce        | Fetch product list                     <br>| News app          | Load latest articles                   <br>| Banking app       | Fetch account balance                  <br>| Weather app       | Get current weather                    <br>| Gallery app       | Load images from storage               <br>| SharedPreferences | Read saved theme or language           <br>| SQLite            | Load local notes or tasks              </pre><h3>Key takeaways for beginners</h3><ul><li>A Future represents a single result that will arrive later.</li><li>FutureBuilder rebuilds the UI automatically when that Future changes state.</li><li>AsyncSnapshot gives you the current state (connectionState), data (data), and any error (error).</li><li>Show a loading indicator while connectionState == ConnectionState.waiting.</li><li>Check snapshot.hasError before using the data.</li><li>Use snapshot.hasData and snapshot.data to display the result.</li><li><strong>Never create a new Future inside </strong><strong>build()</strong> unless you intentionally want the asynchronous operation to restart on every rebuild. Store the Future in initState() (or another lifecycle method) and reuse it.</li></ul><p>Both widgets use the same AsyncSnapshot pattern—the main difference is that a Future emits one result, while a Stream can emit many results over time. In next article we will explain StreamBuilder in next part.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=0dcb56b1a424" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Accessibility widgets in Flutter]]></title>
            <link>https://medium.com/@gauravswarankar/accessibility-widgets-in-flutter-156b173645fe?source=rss-338d813a8d58------2</link>
            <guid isPermaLink="false">https://medium.com/p/156b173645fe</guid>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[flutter-app-development]]></category>
            <category><![CDATA[accessibility]]></category>
            <category><![CDATA[dart]]></category>
            <category><![CDATA[flutter-widget]]></category>
            <dc:creator><![CDATA[Gaurav Swarankar]]></dc:creator>
            <pubDate>Mon, 20 Jul 2026 09:53:21 GMT</pubDate>
            <atom:updated>2026-07-20T09:59:18.235Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/746/0*9SwTC9OX0o-lBWN_.png" /></figure><p><strong>“Close your eyes. Can you still use Instagram? Can you still order food from Swiggy? Can you still book a cab?”</strong></p><p>Most will answer:</p><p><em>“No.” </em>But millions of visually impaired users use these apps every day.</p><h4><strong>How?</strong></h4><p>Because of <strong>screen readers</strong>. A screen reader doesn’t see your UI.</p><ul><li>Android → <strong>TalkBack</strong></li><li>iPhone → <strong>VoiceOver</strong></li></ul><p>It <strong>reads</strong> your app.</p><p>So your Flutter app needs to tell Android and iOS:</p><p><em>“This widget is a button.”</em></p><p><em>“This image is a profile picture.”</em></p><p><em>“This switch is ON.”</em></p><p>That information is called <strong>Semantics</strong>.</p><p>Many beginners think Flutter builds only one tree. Actually <strong>Flutter builds multiple trees.</strong></p><pre>Your Flutter Code<br>       │<br>       ▼<br>Widget Tree<br>       │<br>       ▼<br>Element Tree<br>       │<br>       ▼<br>Render Tree<br>       │<br>       ▼<br>Semantics Tree<br>       │<br>       ▼<br>Android TalkBack<br>iOS VoiceOver</pre><p>Accessibility introduces a <strong>fourth important tree</strong>: The <strong>Semantics Tree</strong>.</p><h3>What is a Semantics Tree?</h3><p>it as a translated version of your UI.</p><p>Suppose your screen looks like this.</p><pre> -----------------------------<br>| 👤  Gaurav Kumar            |<br>|                             |<br>|  [ Follow ]                 |<br> -----------------------------</pre><p>A normal user sees</p><ul><li>Avatar</li><li>Name</li><li>Button</li></ul><p>A blind user doesn’t. The screen reader asks Flutter: <strong><em>“Describe this screen.” </em></strong>Flutter answers using the Semantics Tree.</p><pre>Profile picture<br><br>John Smith<br><br>Follow Button</pre><p>Accessibility widgets are basically <strong>Braille for your app</strong>.</p><h3>What is Semantics Widget?</h3><p>The Semantics widget gives meaning to another widget. Think of it as adding a label.</p><p>Suppose you have: <strong>Icon(Icons.delete) </strong>Everyone knows it’s delete. But TalkBack sees as Image.</p><p>That’s it. So we add Semantics.</p><pre>Semantics(<br>  label: &quot;Delete&quot;,<br>  child: Icon(Icons.delete),<br>)</pre><p>Now TalkBack says Delete.</p><h3>hint</h3><p>Hint tells the user what will happen.</p><p>Example</p><pre>Semantics(<br>  label: &quot;Delete&quot;,<br>  hint: &quot;Double tap to delete this message&quot;,<br>  child: Icon(Icons.delete),<br>)</pre><p>TalkBack:</p><pre>Delete<br>Double tap to delete this message</pre><h3>value</h3><p>Used when the widget changes. Suppose we have a volume slider.</p><pre>========O-------</pre><p>Semantics</p><pre>Semantics(<br>  label: &quot;Volume&quot;,<br>  value: &quot;70 percent&quot;,<br>  child: Slider(...),<br>)</pre><p>TalkBack</p><pre>Volume<br>70 percent</pre><h3>button</h3><p>Flutter doesn’t always know your custom widget behaves like a button.</p><p>Example</p><pre>GestureDetector(<br>  onTap: () {},<br>  child: Container(<br>    padding: EdgeInsets.all(16),<br>    color: Colors.blue,<br>    child: Text(&quot;Login&quot;),<br>  ),<br>)</pre><p>Looks like a button.</p><p>Flutter sees Container.</p><p>TalkBack will say: <strong>Login</strong></p><p>This is Not enough.</p><p>Now</p><pre>Semantics(<br>  button: true,<br>  label: &quot;Login&quot;,<br>  child: GestureDetector(...),<br>)</pre><p>TalkBack</p><pre>Login<br>Button</pre><p>Now users know it is tappable.</p><h3>What is MergeSemantics?</h3><p>Let’s imagine a product card.</p><pre>📱<br>iPhone 16<br>₹90,000</pre><p>Without MergeSemantics TalkBack stops three times.</p><pre>Image<br>iPhone 16<br>90,000 Rupees</pre><p>User keeps swiping. Very annoying.</p><p>With MergeSemantics</p><pre>MergeSemantics(<br>  child: ProductCard(),<br>)</pre><p>TalkBack</p><pre>iPhone 16<br>90,000 Rupees</pre><p>One stop. One announcement. Much better.</p><h3>Another Example</h3><p>Profile Card</p><pre>👤<br>John<br>Software Engineer</pre><p>Without merge will TalkBack consider</p><pre>Image<br>John<br>Software Engineer</pre><p>Three stops. With merge</p><pre>John<br>Software Engineer</pre><p>One stop.</p><h3>What is ExcludeSemantics?</h3><p>This one confuses almost everyone initially. Let’s understand with an example.</p><p>Imagine this widget.</p><pre>Row(<br>  children: [<br>    Icon(Icons.home),<br>    Text(&quot;Home&quot;),<br>  ],<br>)</pre><p>Screen reader says:</p><pre>Home Icon<br><br>Home</pre><p>Two announcements. But both mean the same thing. We don’t need both. So we hide the icon.</p><pre>ExcludeSemantics(<br>  child: Icon(Icons.home),<br>)</pre><p><strong>Now</strong> : Home Only Once</p><h3>Example</h3><p>Imagine someone introduces themselves.</p><pre>Hi,<br>I&#39;m Rahul.<br>My name is Rahul.</pre><p>That’s repetitive. Instead</p><pre>Hi,<br>I&#39;m Rahul.</pre><p>Much better. ExcludeSemantics removes repetition.</p><h3>When All Three Work Together</h3><p>Imagine a custom settings tile.</p><pre>⚙️<br>Settings<br>&gt;</pre><p>Without accessibility TalkBack will see:</p><pre>Image<br>Settings<br>Arrow</pre><p>Three stops. Poor experience.</p><p>Now:</p><pre>Semantics(<br>  label: &quot;Settings&quot;,<br>  hint: &quot;Double tap to open settings&quot;,<br>  button: true,<br>  child: MergeSemantics(<br>    child: Row(<br>      children: [<br>        ExcludeSemantics(<br>          child: Icon(Icons.settings),<br>        ),<br>        ExcludeSemantics(<br>          child: Text(&quot;Settings&quot;),<br>        ),<br>        ExcludeSemantics(<br>          child: Icon(Icons.arrow_forward),<br>        ),<br>      ],<br>    ),<br>  ),<br>)</pre><p>Now TalkBack announces: <em>“Settings. Button. Double tap to open settings.”</em></p><p>This is concise, meaningful, and easy to navigate.</p><h3><strong>Summary:</strong></h3><pre>| Widget               | Think of it as                           | What it does                                          |<br>| -------------------- | ---------------------------------------- | ----------------------------------------------------- |<br>|   Semantics          | Giving someone a name tag                | Adds meaning to a widget                              |<br>|   MergeSemantics     | Putting related papers into one folder   | Combines multiple widgets into one accessible element |<br>|   ExcludeSemantics   | Removing duplicate words from a sentence | Hides unnecessary accessibility information           |</pre><p>Please find attach demo app on github:</p><p><a href="https://github.com/Anonymousgaurav/Accessibility_Widgets">https://github.com/Anonymousgaurav/Accessibility_Widgets</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=156b173645fe" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Native CardFormField gains focus Flutter Stripe (PART — 2)]]></title>
            <link>https://medium.com/@gauravswarankar/native-cardformfield-gains-focus-flutter-stripe-part-2-e0e84e750950?source=rss-338d813a8d58------2</link>
            <guid isPermaLink="false">https://medium.com/p/e0e84e750950</guid>
            <category><![CDATA[flutter-widget]]></category>
            <category><![CDATA[flutter-app-development]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[dart]]></category>
            <category><![CDATA[flutter-stripe]]></category>
            <dc:creator><![CDATA[Gaurav Swarankar]]></dc:creator>
            <pubDate>Thu, 16 Jul 2026 04:09:44 GMT</pubDate>
            <atom:updated>2026-07-16T04:09:44.327Z</atom:updated>
            <content:encoded><![CDATA[<h3><em>The keyboard appears for a split second after pressing a button.</em></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/809/0*kb5wxarsBR2UBKGB.png" /></figure><h3>Why This Bug Was Interesting</h3><p>Every Flutter developer eventually encounters a bug that looks simple but isn’t.</p><p>You might think:</p><ul><li>Maybe FocusNode is wrong.</li><li>Maybe TextInput.hide() isn&#39;t working.</li><li>Maybe setState() is rebuilding too much.</li></ul><p>But sometimes <strong>none of those are the real cause.</strong></p><p>Our Stripe CardFormField issue is one of those cases. The keyboard flicker wasn’t caused by Flutter. It happened because <strong>Flutter and Android were both trying to control the keyboard at the same time.</strong></p><h4><strong>How Flutter Receives Keyboard Input</strong></h4><p>Before discussing Stripe, we need to understand how Flutter normally handles text input. We already discussed this in <a href="https://medium.com/@gauravswarankar/the-hidden-difference-between-unfocus-and-textinput-hide-in-flutter-part-1-105a6d135c4c">Part — 1 of this article.</a></p><pre>User taps TextField<br>        │<br>        ▼<br>Flutter gives it Focus<br>        │<br>        ▼<br>FocusManager updates<br>        │<br>        ▼<br>Flutter tells Android:<br>&quot;I need the keyboard.&quot;<br>        │<br>        ▼<br>Android IME opens</pre><h3>IME</h3><p>IME stands for <em>Input Method Editor. </em>Most developers simply call it <em>Soft Keyboard.</em></p><p>Examples:</p><ul><li>Android keyboard</li><li>Gboard</li><li>Samsung Keyboard</li><li>SwiftKey</li></ul><p>Flutter does <strong>not</strong> create the keyboard. Android does. Flutter only requests Android to show or hide it.</p><p>Flutter communicates with Android using the TextInput channel. When Flutter wants the keyboard:</p><pre>Flutter<br><br>↓<br><br>TextInput.show<br><br>↓<br><br>Android IME</pre><p>When Flutter wants to hide it:</p><pre>SystemChannels.textInput.invokeMethod(<br>    &#39;TextInput.hide&#39;);</pre><p>Android receives that request. Normally that’s enough.</p><h3><strong>Why Stripe Is Different?</strong></h3><p>A normal TextField looks like this.</p><pre>Flutter<br>     │<br>     ▼<br>TextField</pre><p>Everything belongs to Flutter. But Stripe is different.</p><pre>Flutter<br><br>↓<br><br>Platform View<br><br>↓<br><br>Android EditTexts</pre><p>The card number field, expiry field, and CVC field are real Android views.</p><p>Flutter does not own them.</p><p><strong>Why Platform Views Are Difficult?</strong></p><p>Platform views introduce a second UI framework. Instead of Flutter we now have Flutter + Android. Both can request focus. Both can request the keyboard. Both can rebuild. Both can animate. This is why platform views are more complex than ordinary widgets.</p><h4>The Android Keyboard System</h4><p>Android has a service called It controls</p><ul><li>opening keyboard</li><li>closing keyboard</li><li>moving focus</li><li>connecting EditTexts</li></ul><p>Whenever an EditText gains focus</p><p>Android automatically says Open keyboard. Flutter cannot stop this with TextInput.hide() because Android owns the EditText.</p><h3><strong>Why Our Bug Happened:</strong></h3><pre>User types card<br><br>↓<br><br>CardFormField owns focus<br><br>↓<br><br>User presses Add<br><br>↓<br><br>Flutter hides keyboard<br><br>↓<br><br>Stripe begins createPaymentMethod()<br><br>↓<br><br>Native EditText gains focus again<br><br>↓<br><br>Android opens keyboard<br><br>↓<br><br>Flutter hides keyboard again<br><br>↓<br><br>Flicker</pre><p>Nothing was actually broken. Both frameworks were simply doing their jobs. Many developers try:</p><pre>FocusManager.instance.primaryFocus?.unfocus();<br><br>await SystemChannels.textInput.invokeMethod(<br>    &#39;TextInput.hide&#39;);</pre><p>That removes Flutter’s focus. But Android still has</p><pre>EditText<br><br>↓<br><br>requestFocus()</pre><p>So Android opens the keyboard again.</p><p>This is why our Flutter solution worked only about <strong>80–90%</strong> of the time.</p><p>The remaining 10–20% required native Android code. Flutter cannot directly execute Android code. Instead, Flutter and Android communicate through a bridge called a <strong>MethodChannel</strong>.</p><pre>Flutter (Dart)<br><br>        │<br><br>MethodChannel<br><br>        │<br><br>Android (Kotlin)</pre><p>we will do communication bridge between Flutter (Dart) and Android (Kotlin). Flutter cannot directly execute Android methods.</p><p>Similarly Android cannot directly call Dart methods. They need a communication bridge. That bridge is called a <strong>MethodChannel</strong>. Flutter creates the channel.</p><pre>static const MethodChannel _imeChannel =<br>    MethodChannel(&quot;your_app_name/ime_control&quot;);</pre><p>Flutter says:</p><blockquote><em>“I’m going to communicate using a channel named </em><strong><em>your_app_name/ime_control</em></strong><em>.”</em></blockquote><p>Nothing happens yet. It simply creates a communication endpoint. Android will create same channel.</p><pre>MethodChannel(<br>    flutterEngine.dartExecutor.binaryMessenger,<br>    IME_CHANNEL<br>)</pre><p>where IME_CHANNEL:</p><p>private val IME_CHANNEL = “your_app_name/ime_control”</p><h4>Did you Notice something ?</h4><p>Flutter:</p><pre>your_app_name/ime_control</pre><p>Android:</p><pre>your_app_name/ime_control</pre><p>These names must be identical. Now Android starts listening:</p><pre>.setMethodCallHandler { call, result -&gt;</pre><p>means <em>“Android is now waiting for Flutter to send a message.” </em>Nothing happens until Flutter calls the channel. Flutter Calls Android Somewhere in Dart we write:</p><pre>await _imeChannel.invokeMethod(<br>    &quot;suppressSoftInput&quot;);</pre><p>Flutter sends this message.</p><pre>Channel<br><br>Method Name<br><br>↓<br><br>suppressSoftInput</pre><p>This message travels to Android. Android Receives the Message. Now this code executes.</p><pre>when (call.method)</pre><p>Think like this:</p><pre>Flutter said<br><br>↓<br><br>&quot;suppressSoftInput&quot;<br><br>↓<br><br>Which method is this?<br><br>↓<br><br>Run suppressSoftInput()</pre><p>If Flutter instead sends → invokeMethod(“restoreSoftInput”) then Android executes restoreSoftInput().</p><h3>What’s Next?</h3><p>In this article, we explored how Flutter manages focus, the relationship between FocusManager, FocusNode, and the platform&#39;s Input Method Editor (IME), and why simply hiding the keyboard isn&#39;t always enough when working with embedded native Android views such as Stripe CardField, Google Maps, or other Platform Views.</p><p>In the next article, we’ll move beyond theory and dive into the native Android implementation. We’ll learn how to communicate between Flutter and Android using <strong>Method Channels</strong>, and implement native APIs to programmatically <strong>hide</strong>, <strong>show</strong>, <strong>suppress</strong>, and <strong>restore</strong> the Android IME keyboard. We’ll also explore how this approach helps eliminate keyboard flickering, prevents focus conflicts between Flutter and native views, and provides a smoother user experience when integrating Platform Views into Flutter applications.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e0e84e750950" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Hidden Difference Between unfocus() and TextInput.hide() in Flutter (PART — 1)]]></title>
            <link>https://medium.com/@gauravswarankar/the-hidden-difference-between-unfocus-and-textinput-hide-in-flutter-part-1-105a6d135c4c?source=rss-338d813a8d58------2</link>
            <guid isPermaLink="false">https://medium.com/p/105a6d135c4c</guid>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[flutter-keyboard-focus]]></category>
            <category><![CDATA[flutter-widget]]></category>
            <category><![CDATA[dart]]></category>
            <category><![CDATA[flutter-app-development]]></category>
            <dc:creator><![CDATA[Gaurav Swarankar]]></dc:creator>
            <pubDate>Tue, 14 Jul 2026 08:17:42 GMT</pubDate>
            <atom:updated>2026-07-14T08:17:42.597Z</atom:updated>
            <content:encoded><![CDATA[<h3>Encountered keyboard issues in Flutter?</h3><p><strong>Have you ever encountered keyboard or focus issues in your Flutter app while integrating native SDKs like Stripe, Google Maps, WebView, Camera, or other Platform Views?</strong></p><p>you’ve probably run into strange keyboard behavior — especially when working with native components such as <strong>Stripe CardFormField</strong>, <strong>Google Maps</strong>, <strong>WebView</strong>, <strong>Camera</strong>, or other Platform Views.</p><p><strong>Some common symptoms include:</strong></p><ul><li>The keyboard won’t dismiss.</li><li>The keyboard disappears and immediately comes back.</li><li>FocusScope.of(context).unfocus() doesn&#39;t seem to work.</li><li>TextInput.hide() works on Android but behaves differently on iOS.</li><li>Navigation causes the keyboard to reopen unexpectedly.</li></ul><p>If you’ve experienced any of these, you’re not alone. 😄</p><p>In reality, Flutter is doing exactly what it was designed to do. The confusion comes from assuming that <strong>removing focus</strong> and <strong>hiding the keyboard</strong> are the same operation. They are not.</p><p>In this article, we’ll explore how Flutter manages focus, how the Flutter Engine communicates with Android and iOS, and why understanding this architecture will save you hours of debugging keyboard-related issues.</p><h3>Hidden Difference Between unfocus() and TextInput.hide() in Flutter</h3><p>Every Flutter developer has written code like this:</p><pre>FocusManager.instance.primaryFocus?.unfocus();</pre><p>or</p><pre>await SystemChannels.textInput.invokeMethod(&#39;TextInput.hide&#39;);</pre><p>Both make the keyboard disappear.</p><p>So naturally the question is:</p><p><strong><em>Are they actually the same?</em></strong></p><p>The answer is <strong>No.</strong></p><p>One changes <strong>Flutter’s focus system</strong>.</p><p>The other talks directly to the <strong>native operating system</strong>. Understanding this difference makes keyboard bugs, Stripe CardFormField issues, WebViews, PlatformViews, and custom input widgets much easier to debug. Flutter has its own focus management system.</p><p>Think of focus as answering one simple question:</p><p><strong><em>Which widget is currently receiving keyboard input?</em></strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/614/1*iE1FRYaL0-iB2k33l10Vng.png" /></figure><p>When the cursor is blinking then focus is on First Name. Internally Flutter knows</p><p>FocusManager<br> │<br> ▼<br> FocusNode<br> │<br> ▼<br> TextField</p><p>Only one widget usually has the primary focus. You can inspect it anytime. Only one widget generally owns the keyboard at a time.</p><pre>FocusManager.instance.primaryFocus</pre><h3>Focus System Architecture</h3><p>Flutter has an entire focus management system.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/820/1*ujniwSn0OacO8baRrNRIig.png" /></figure><p>There are two important classes.</p><ul><li>FocusManager</li><li>FocusNode</li></ul><h3>What is FocusManager?</h3><p>FocusManager is the <strong>global manager</strong> of every focusable widget in the application.</p><p>There is only one FocusManager. <em>“The traffic controller of keyboard focus.”</em></p><p>It always knows</p><ul><li>Which widget currently has focus</li><li>Which widget lost focus</li><li>Which widget should receive the next focus</li></ul><p>Internally FocusManager.instance is a singleton.</p><p>Meaning</p><pre>Entire App<br>     │<br>     ▼<br>FocusManager.instance</pre><p>Everything goes through this object.</p><h3>What is FocusNode?</h3><p>FocusNode represents the focus state of <strong>one widget</strong>.</p><p>Think of it as an ID card.</p><p>Every TextField may have one.</p><pre>Email TextField<br>      │<br>      ▼<br> EmailFocusNode<br><br>Password TextField<br>      │<br>      ▼<br> PasswordFocusNode</pre><p>Example:</p><pre>final emailFocus = FocusNode();<br><br>TextField(<br>  focusNode: emailFocus,<br>)<br><br>Now:<br><br>TextField<br>      │<br>      ▼<br> emailFocus</pre><p>Relationship:</p><pre>FocusManager<br>      │<br>      │ manages<br>      ▼<br> FocusNode<br>      │<br>      │ attached to<br>      ▼<br> TextField</pre><p>FocusManager never directly manages TextField.</p><h3>Primary Focus</h3><p>Flutter exposes</p><pre>FocusManager.instance.primaryFocus</pre><p>This means <em>“The widget currently receiving keyboard input.” </em>Suppose Email is active.</p><pre>FocusManager<br><br>primaryFocus<br>      │<br>      ▼<br>Email FocusNode</pre><p>If you want to print active widget focus node:</p><pre>print(FocusManager.instance.primaryFocus);</pre><p>you will get output like this → FocusNode#12345 which belongs to the active widget.</p><h3>requestFocus()</h3><p>Suppose user presses Next. Instead of tapping manually. You can move focus yourself.</p><pre>passwordFocus.requestFocus();</pre><pre>requestFocus()<br><br>      │<br><br>      ▼<br><br>FocusManager<br><br>      │<br><br>      ▼<br><br>Password becomes focused</pre><h3>unfocus()</h3><p>Now suppose user taps outside. Flutter removes focus.</p><pre>emailFocus.unfocus();</pre><h3>FocusScope</h3><p>One screen can have many FocusNodes. Flutter groups them into a FocusScope.</p><pre>Login Screen<br><br>FocusScope<br>      │<br>      ├── Email<br>      ├── Password<br>      ├── OTP<br>      └── Login Button</pre><p>Calling FocusScope.of(context).nextFocus(); Moves</p><pre>Email<br><br>↓<br><br>Password<br><br>↓<br><br>OTP<br><br>↓<br><br>Login</pre><h3>Focus Tree</h3><p>Flutter actually builds a tree.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tsKiebir0z-rmLPSFP58OQ.png" /></figure><p>This tree helps Flutter know where focus should move when users press Tab, Shift+Tab, or navigate with a keyboard.</p><h3>Why FocusNode is important</h3><p>Without FocusNode Flutter cannot</p><ul><li>move cursor</li><li>detect focus</li><li>remove focus</li><li>highlight active widget</li><li>support keyboard shortcuts</li><li>support accessibility</li></ul><p>The key idea is that <strong>the keyboard doesn’t belong to a </strong><strong>TextField directly</strong>. The keyboard sends input to the <strong>currently focused </strong><strong>FocusNode</strong>, and the FocusManager is responsible for deciding which FocusNode that is at any given moment. This separation allows Flutter to support seamless focus traversal, hardware keyboards, accessibility, and complex widget hierarchies across platforms.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=105a6d135c4c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Microsoft Outlook Calendar Integration (Part-1)]]></title>
            <link>https://medium.com/@gauravswarankar/microsoft-outlook-calendar-integration-87c6b25ec53f?source=rss-338d813a8d58------2</link>
            <guid isPermaLink="false">https://medium.com/p/87c6b25ec53f</guid>
            <category><![CDATA[outlook]]></category>
            <category><![CDATA[outlook-integration]]></category>
            <category><![CDATA[calendar-integration]]></category>
            <category><![CDATA[microsoft-outlook]]></category>
            <dc:creator><![CDATA[Gaurav Swarankar]]></dc:creator>
            <pubDate>Wed, 08 Jan 2025 08:24:20 GMT</pubDate>
            <atom:updated>2025-01-10T09:42:46.491Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*u9RijwqxHGyM135C" /></figure><p>Microsoft Calendar integration is the process of connecting a Microsoft Calendar, such as Outlook Calendar or Microsoft 365 Calendar, with other applications to enable seamless scheduling, event management, and collaboration. This integration can be achieved using APIs, connectors, or third-party tools.</p><h3>How to Implement Microsoft Calendar Integration</h3><p><strong>Use Microsoft Graph API:</strong></p><ul><li>Provides robust features for managing calendar events programmatically.</li></ul><p><strong>Use Native Connectors:</strong></p><ul><li>Tools like Zapier, Power Automate, or IFTTT simplify integration.</li></ul><p><strong>Custom Development:</strong></p><ul><li>Build tailored integrations using development platforms or libraries.</li></ul><p>So in this article we are going to follow Microsoft Graph API. Let’s go step by step.</p><ol><li>Create your account on Azure portal.</li><li>Register your application by Navigating to “Azure Active Directory” &gt; “App registrations.”</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RT3Bv_MAHbQLkQew1SuE1A.png" /></figure><p>3. Click on “New Registration.”</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lxWLl_Ok9IoLeE0BiMkf3A.png" /></figure><p>4. Provide a name for your app, select account types, and enter a redirect URI (e.g., http://localhost:3000 for testing)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6I3bESAVPIpHmZ9hpdT0Ew.png" /></figure><p>5. <strong>Take Note of Application Credentials</strong>:</p><ul><li>Once registered, note the <strong>Application (Client) ID</strong> and <strong>Directory (Tenant) ID.</strong></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GfNMhfxZYvgBN3NlpU_jMA.png" /></figure><ul><li>Generate a <strong>Client Secret</strong> under the “Certificates &amp; Secrets” section.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*peTsmY7qEbSj9X_igMX79w.png" /></figure><p>Congrats. we have regsitered our application on Azure portal.</p><p>Now we have to configure API Permissions.</p><p><strong>Your app needs permissions to access users’ calendars.</strong></p><ol><li>Go to your app registration.</li><li>Navigate to <strong>API Permissions under Manage section</strong>.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-Hc-KL9zem0cwMZ1vWdPVg.png" /></figure><p>3. Click <strong>Add a Permission</strong>:</p><p>4. Select <strong>Microsoft Graph</strong>.</p><ul><li>Add <strong>Delegated Permissions</strong> (if the app will act on behalf of a user) like <strong>Calendars.ReadWrite offline_access User.Read</strong></li><li>Optionally, add <strong>Application Permissions</strong> for server-to-server calls.</li></ul><p>5. Grant <strong>Admin Consent</strong> for your organization if required.</p><p>We have done with API Permissions.</p><h3>Conclusion</h3><p>In this article, we took the first crucial steps toward integrating Microsoft Outlook Calendar by registering our application in Azure Active Directory and configuring the necessary API permissions. These actions lay the foundation for secure communication with Microsoft Graph API, enabling us to access and manage calendar data in future steps. Stay tuned as we move forward to implement authentication and interact with the calendar API in the next article!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=87c6b25ec53f" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[KeyCloak Login Options (Part-3)]]></title>
            <link>https://medium.com/@gauravswarankar/keycloak-login-options-part-3-e55b039bbfa2?source=rss-338d813a8d58------2</link>
            <guid isPermaLink="false">https://medium.com/p/e55b039bbfa2</guid>
            <category><![CDATA[keycloak]]></category>
            <category><![CDATA[keycloak-integration]]></category>
            <category><![CDATA[keycloakjs]]></category>
            <category><![CDATA[keycloak-theme]]></category>
            <category><![CDATA[login]]></category>
            <dc:creator><![CDATA[Gaurav Swarankar]]></dc:creator>
            <pubDate>Mon, 23 Dec 2024 13:17:58 GMT</pubDate>
            <atom:updated>2024-12-23T13:17:58.922Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/703/1*E6q3iwapc03avKSL8sF_zg.png" /></figure><p>Keycloak offers various built-in features for the login page.</p><h4>Enabling “Forgot Password”</h4><p>To allow users to reset their passwords or OTPs:</p><ol><li>Go to <strong>Realm Settings</strong> in the menu.</li><li>Click the <strong>Login</strong> tab</li></ol><p>Built-in login features, like “Forgot Password,” enhance usability, security, and user experience. They simplify account recovery, reduce support requests, and ensure seamless access to applications.</p><h4>Use Cases:</h4><ol><li><strong>Forgot Password Feature</strong>:</li></ol><ul><li><strong>Why?</strong> Users often forget their passwords. A built-in “Forgot Password” feature helps them reset it without contacting support, improving user satisfaction.</li><li><strong>Example:</strong><br>In an <strong>e-commerce app</strong>, if a user forgets their password while trying to complete a purchase, they can use the “Forgot Password” option to reset it instantly and proceed without abandoning their cart.</li></ul><p>3. Toggle <strong>Forgot password</strong> to <strong>ON</strong>.</p><p>A Forgot Password? link displays in your login pages.</p><p>Forgot password link</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/501/0*0kP9-KEcugLz5oKk.png" /></figure><p>4. Set the <strong>Host</strong> and <strong>From</strong> fields in the Email tab so Keycloak can send password reset emails.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GkhXeo822w36WrbatnaTXA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KaFzZ6EU9sp_yWe5H9vxqA.png" /></figure><p>5. When users click the “Forgot Password” link, they can enter their username or email address to get an email with a link to reset their password.</p><p>6. The email text for password reset can be customized. <a href="https://www.keycloak.org/docs/26.0.7/server_development/">Refer to the Server Developer Guide for details.</a></p><p>When users click the reset link in the email, Keycloak prompts them to update their password. If they use an OTP generator, Keycloak will also ask them to reconfigure it. For higher security, you can choose to prevent users from resetting their OTP generator via email.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/501/0*0zcUSrxrqs2KOEeC.png" /></figure><p>To modify the behavior for resetting OTP during password resets, follow these steps:</p><p>Go to the <strong>Authentication</strong> menu.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Mrd0yPtleL8AMOr2VZTniA.png" /></figure><ol><li>Click the <strong>Flows</strong> tab.</li><li>Select the <strong>Reset Credentials</strong> flow.</li><li>Set the <strong>Reset — Conditional OTP</strong> sub-flow requirement to <strong>Disabled</strong> if you want to prevent OTP reset.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uLXzGfOMZcKeq_Uup7lVhw.png" /></figure><p>In the <strong>Authentication</strong> menu, click the <strong>Required actions</strong> tab.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MoIDbxXf3evbO0L_d6Ppkg.png" /></figure><p>Ensure that <strong>Update Password</strong> is enabled.</p><h4>Enabling Remember Me</h4><p>To enable the <strong>Remember Me</strong> feature in Keycloak:</p><ol><li>Go to the <strong>Realm Settings</strong> menu.</li><li>Click the <strong>Login</strong> tab.</li><li>Toggle the <strong>Remember Me</strong> switch to <strong>On</strong>.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/415/1*RDjkpoumrqFmyWLTSSBu7w.png" /></figure><p>When enabled, the login page will display a “Remember Me” checkbox. If a user selects it during login, their session remains active even after closing the browser, as the login cookie becomes persistent instead of session-only.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/501/0*tePQrdieCW-82MJp.png" /></figure><h3>ACR to Level of Authentication (LoA) Mapping</h3><p>ACR to Level of Authentication (LoA) Mapping links an <strong>Authentication Context Class Reference (ACR)</strong> value to a <strong>Level of Authentication (LoA)</strong>. This mapping helps define and enforce the security level of user authentication required for specific scenarios.</p><h3>What is ACR?</h3><p>ACR stands for <strong>Authentication Context Class Reference</strong>, which is a value used in OpenID Connect (OIDC) to describe the context or method of user authentication.<br>For example:</p><ul><li>ACR values may indicate that a user logged in using a password, biometrics, or multi-factor authentication (MFA). Multi-Factor Authentication (MFA) is a security process requiring users to verify their identity using <strong>two or more authentication factors</strong> from different categories. It enhances security by combining multiple layers of protection.</li></ul><h3>Three Categories of Authentication Factors</h3><ol><li><strong>Something You Know</strong><br>Information only the user knows, such as:</li></ol><ul><li>Passwords</li><li>PINs</li><li>Security questions</li></ul><p><strong>2. Something You Have</strong><br>Physical items or tokens the user possesses, such as:</p><ul><li>Mobile phones (for OTP or app-based authentication)</li><li>Security tokens (e.g., hardware keys like YubiKey)</li><li>Smart cards</li></ul><p><strong>3. Something You Are</strong><br>Biometric traits unique to the user, such as:</p><ul><li>Fingerprints</li><li>Facial recognition</li><li>Iris scans</li><li>Voice recognition</li></ul><h3>How MFA Works</h3><p>When logging into a system, the user must provide credentials from at least two of the above categories.<br><strong>Example Workflow</strong>:</p><ol><li><strong>Step 1</strong>: Enter a username and password (<strong>Something You Know</strong>).</li><li><strong>Step 2</strong>: Receive a One-Time Password (OTP) on a mobile phone and enter it (<strong>Something You Have</strong>).</li><li><strong>Optional Step 3</strong>: Use fingerprint verification (<strong>Something You Are</strong>) for higher security requirements.</li></ol><h3>Real-World Examples</h3><ol><li><strong>Online Banking</strong></li></ol><ul><li><strong>Step 1</strong>: Enter username and password to access the account.</li><li><strong>Step 2</strong>: Confirm identity by entering an OTP sent to the registered phone.</li></ul><p><strong>2. Workplace Access</strong></p><ul><li><strong>Step 1</strong>: Swipe a smart card to access the office.</li><li><strong>Step 2</strong>: Provide a fingerprint scan at the door.</li></ul><p><strong>3. Cloud Services (e.g., Google)</strong></p><ul><li><strong>Step 1</strong>: Log in with a password.</li><li><strong>Step 2</strong>: Verify login with an authentication app like Google Authenticator or receive a push notification on a trusted device.</li></ul><h3>What is LoA Mapping?</h3><p>LoA (Level of Authentication) mapping refers to the process of associating specific authentication methods with a <strong>numeric value</strong> that represents their strength or security level. The numeric <strong>Level of Authentication (LoA)</strong> helps define the assurance or confidence that the user is who they claim to be, based on the method(s) used to authenticate them.</p><h3>How LoA Mapping Works</h3><ol><li><strong>Define Levels of Authentication</strong>: Assign numeric values to different authentication strengths. For example:</li></ol><ul><li><strong>LoA 1</strong>: Basic authentication (e.g., username and password).</li><li><strong>LoA 2</strong>: Two-factor authentication (e.g., password + OTP).</li><li><strong>LoA 3</strong>: Advanced authentication (e.g., password + biometric scan).</li><li><strong>LoA 4</strong>: Very high-security authentication (e.g., hardware tokens + biometric + geo-location checks).</li></ul><p><strong>2. Associate Authentication Contexts (ACRs)</strong>: The authentication method (or context) is mapped to the numeric LoA. This allows systems to enforce security policies based on the required level of assurance.</p><p><strong>3. Use in Applications</strong>: When a user accesses a system or service, the authentication method they use determines the LoA, and access is granted only if the LoA meets or exceeds the system’s requirements.</p><h3>Real-World Examples of LoA Mapping</h3><ol><li><strong>Banking Applications</strong></li></ol><ul><li><strong>LoA 1</strong>: A user logs in to check account balances using only a password.</li><li><strong>LoA 2</strong>: A user makes a fund transfer, requiring OTP verification sent to their phone.</li><li><strong>LoA 3</strong>: A user accesses sensitive features like account deletion, requiring a biometric scan in addition to an OTP.</li></ul><p><strong>2. Government Services</strong></p><ul><li><strong>LoA 1</strong>: Citizens log in to view public service announcements using a simple username and password.</li><li><strong>LoA 2</strong>: To file taxes, they use two-factor authentication (password + OTP).</li><li><strong>LoA 3</strong>: For higher-level services (e.g., applying for visas or accessing personal health records), users authenticate using a hardware token and biometric scan.</li></ul><p><strong>3. Corporate Systems</strong></p><ul><li><strong>LoA 1</strong>: Employees log in to check their work schedules using passwords.</li><li><strong>LoA 2</strong>: Employees access confidential internal documents requiring MFA (password + mobile push notification).</li><li><strong>LoA 3</strong>: Administrators modify system configurations requiring a password, hardware token, and location verification.</li></ul><blockquote>In the general settings of a realm, you can define which Authentication Context Class Reference (ACR) value is mapped to which Level of Authentication (LoA).</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*52jRS-RqcLLnJ4plHOgOOQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*USUROi-pcbWaxpXFhjNuMw.png" /></figure><p><strong>Key (ACR)</strong>: Enter a string representing the authentication method or context. For example:</p><ul><li>&quot;basic&quot;: Username and password.</li><li>&quot;mfa&quot;: Multi-factor authentication (e.g., password + OTP).</li><li>&quot;passwordless&quot;: Authentication without passwords (e.g., biometrics or magic links).</li></ul><p><strong>Value (LoA)</strong>: Enter a numeric value representing the strength of the authentication method:</p><ul><li>1: Basic authentication (low assurance).</li><li>2: Multi-factor authentication (medium assurance).</li><li>3: Passwordless or hardware token-based authentication (high assurance).</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hlM6YES76Ji7WcOkcc0j5A.png" /></figure><h3>How to Use This Functionality?</h3><ol><li><strong>Set the Mapping</strong>:</li></ol><ul><li>Go to <strong>Realm Settings</strong> → <strong>General Settings</strong>.</li><li>Under <strong>ACR to LoA Mapping</strong>, enter the ACRs and their corresponding LoAs.</li></ul><p>2. To <strong>configure authentication flows</strong> in Keycloak that check the <strong>Level of Authentication (LoA)</strong> based on the <strong>mapped ACR</strong>, you need to set up <strong>authentication flows</strong> within the Keycloak admin console. These flows are used to determine the level of authentication required before granting access to a user.</p><h3><strong>Process to Configure Authentication Flows Based on ACR to LoA Mapping</strong></h3><h4>1. Access Authentication Flows:</h4><ul><li>In the <strong>Keycloak Admin Console</strong>, go to <strong>Authentication</strong> from the left-hand menu.</li><li>Then, click on the <strong>Flows</strong> tab at the top of the page.</li></ul><h4>2. Create or Modify an Authentication Flow:</h4><ul><li><strong>Create a new flow</strong> or <strong>edit an existing flow</strong> to customize the authentication process.</li><li>Click <strong>Add flow</strong> to create a new flow or click the <strong>Edit</strong> icon next to an existing flow if you want to modify it.</li></ul><p>When configuring authentication flows in Keycloak, the two options you’re seeing — <strong>Basic Flow</strong> and <strong>Client Flow</strong> — are different types of authentication flows that serve specific purposes:</p><h3>1. Basic Flow</h3><ul><li><strong>Purpose</strong>: This is the most commonly used flow, designed for general authentication scenarios.</li><li><strong>Use Case</strong>: It’s used for authenticating users through traditional means such as username/password, OTP, etc.</li><li><strong>Example</strong>: When a user tries to log in via the browser, this flow checks the username/password, may ask for OTP if multi-factor authentication (MFA) is enabled, and then grants access to the system.</li><li><strong>Common Flow Types</strong>: Login with username/password, OTP verification, password reset, etc.</li></ul><p><strong>Example Configuration</strong>:</p><ul><li>If the user tries to log in, they are first authenticated using their <strong>username and password</strong> (LoA 1). Then, if they are accessing a sensitive action, they are prompted for <strong>OTP (LoA 2)</strong>.</li></ul><h3>2. Client Flow</h3><ul><li><strong>Purpose</strong>: This flow type is specifically designed for <strong>client-side applications</strong> (e.g., mobile apps, service-to-service authentication, etc.).</li><li><strong>Use Case</strong>: Used when a client (like a mobile app or an API) authenticates itself with Keycloak to obtain an access token (for OAuth or OpenID Connect flows).</li><li><strong>Example</strong>: When a mobile app needs to authenticate a user or request an access token to access backend APIs, a client flow is used.</li></ul><h3>Which One to Choose?</h3><ul><li><strong>Basic Flow</strong>: If you are working on user login and want to configure the authentication steps based on <strong>Level of Authentication (LoA)</strong>, go with the <strong>Basic Flow</strong>. This is typically used for browser-based login scenarios where user credentials are involved.</li><li><strong>Client Flow</strong>: If you are working with client-side apps or API integrations (e.g., when your application needs to authenticate itself to access Keycloak or other resources), then you should use <strong>Client Flow</strong>.</li></ul><h3>For Basic Flow:</h3><p>If you choose <strong>Basic Flow</strong>, you can then proceed to configure specific <strong>execution steps</strong> in the flow:</p><ol><li><strong>Add Executions</strong>: You can add execution steps like:</li></ol><ul><li>Username/password form.</li><li>OTP verification for multi-factor authentication (LoA 2).</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mYg0xZdVjz1relaIP4oU-A.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YcFZ2z22kwCHX41dphfWKQ.png" /></figure><h3>For Client Flow:</h3><p>The <strong>executions</strong> we listed in the <strong>Client Flow</strong> in Keycloak are methods for <strong>client authentication</strong>. These executions define how Keycloak validates the <strong>client</strong> (i.e., the application or service trying to authenticate) when it attempts to interact with Keycloak.</p><h3>1. Client ID and Secret:</h3><p>This is the most common method for authenticating clients. When a client application (like a web app or mobile app) needs to authenticate, it sends its <strong>client ID</strong> and <strong>client secret</strong> (like a username and password for the application).</p><ul><li>The client sends its <strong>client_id</strong> and <strong>client_secret</strong> either in the request parameters or in the <strong>Authorization header</strong> (using Basic authentication).</li><li>A backend service that interacts with Keycloak to get an <strong>access token</strong> for accessing a protected API would authenticate using its <strong>client_id</strong> and <strong>client_secret</strong>.</li><li>This is used when you want to authenticate using traditional client credentials (client ID + secret).</li></ul><h3>2. Signed JWT:</h3><ul><li>In this method, the client uses a <strong>signed JSON Web Token (JWT)</strong> to authenticate. The JWT is <strong>signed</strong> with the <strong>client’s private key</strong>, and Keycloak will verify this signature using the client’s <strong>public key</strong>.</li><li>The client generates a JWT that includes information like the <strong>client ID</strong> and some claims (additional information), signs it with its <strong>private key</strong>, and sends it to Keycloak. Keycloak verifies the signature using the <strong>public key</strong> that it already has for the client.</li><li>A client application that wants to authenticate without sending sensitive credentials like a secret could use <strong>JWT</strong>. For example, a secure service-to-service communication where the client securely signs a JWT for authentication.</li><li>This is useful when you want a more secure, token-based authentication that avoids sending secrets over the wire.</li></ul><h3>3. Signed JWT with Client Secret:</h3><ul><li>This is a variation of the <strong>Signed JWT</strong> method, but here the client <strong>signs the JWT</strong> using its <strong>client secret</strong> instead of a private key.</li><li>The client generates a JWT and <strong>signs it</strong> with the <strong>client secret</strong>. Keycloak will then verify this JWT against the client’s known secret.</li><li>This is useful when you want to use a <strong>JWT-based authentication</strong> but prefer to use the <strong>client secret</strong> for signing instead of managing private keys. It is a simpler option for clients that don’t have access to private keys.</li><li>This method is good if you want to authenticate using JWTs but still prefer using secrets over private keys.</li></ul><h3>4. X509 Certificate:</h3><ul><li>This method allows a client to authenticate using a <strong>client certificate</strong> (an <strong>X.509 certificate</strong>).</li><li>The client presents a certificate (which includes the <strong>client’s public key</strong>) during the authentication process, and Keycloak verifies the certificate against a list of trusted certificates. The client also proves its identity by signing with its private key.</li><li>A high-security environment where client-server communication requires certificates. For example, an enterprise service using mutual TLS (mTLS) for secure authentication.</li><li>This method is used when you want to authenticate clients in environments that rely on <strong>public key infrastructure (PKI)</strong>, using certificates instead of passwords or secrets.</li></ul><h3>When to Use Each Execution in Client Flow:</h3><ul><li><strong>Client ID and Secret</strong>: Ideal for most client applications that require a straightforward and simple authentication method using a <strong>client ID</strong> and <strong>secret</strong>.</li><li><strong>Signed JWT</strong>: Use when you want a more <strong>secure, token-based</strong> authentication, and avoid sending the <strong>client secret</strong> in requests.</li><li><strong>Signed JWT with Client Secret</strong>: A hybrid solution that allows you to authenticate using a <strong>JWT</strong> while still signing it with the <strong>client secret</strong>. It provides a good balance between using tokens and keeping secrets secure.</li><li><strong>X509 Certificate</strong>: Use this in high-security environments where you want to authenticate clients using certificates (for example, in scenarios involving <strong>mTLS</strong> or strict identity verification).</li></ul><p>By selecting the appropriate <strong>execution</strong> in the <strong>client flow</strong>, you can customize how your <strong>clients</strong> authenticate with Keycloak based on your security needs and requirements.</p><h3><strong>Summary</strong></h3><p>we discussed key login options and authentication configurations in Keycloak, which are crucial for enhancing security and user experience:</p><ol><li><strong>Forgot Password</strong>: This feature allows users to reset their passwords without contacting support. It helps improve user satisfaction and reduces support requests. If not configured, users may be unable to recover their accounts on their own, leading to frustration and possible abandonment of your app.</li><li><strong>Remember Me</strong>: Enabling this feature allows users to stay logged in even after closing the browser, enhancing user convenience. Without it, users would need to log in repeatedly, which may lead to a less user-friendly experience.</li><li><strong>ACR to LoA Mapping</strong>: This feature links Authentication Context Class Reference (ACR) values to Levels of Authentication (LoA). It allows systems to enforce varying levels of security, depending on the authentication method (e.g., username/password, multi-factor authentication). Without proper mapping, your application may not enforce appropriate security policies for different actions, potentially exposing sensitive data.</li><li><strong>Authentication Flows</strong>: These define the sequence of authentication steps a user or client must complete. Flows such as <strong>Basic Flow</strong> (for general user login) and <strong>Client Flow</strong> (for service-to-service authentication) help secure access based on the required security level. Without customized flows, you might not be able to enforce multi-factor authentication or handle client-specific authentication properly, leading to security risks.</li></ol><p>These configurations and features enhance both user experience and security. If not properly implemented, users may face difficulties like account recovery issues, repeated logins, or security risks due to insufficient authentication checks.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e55b039bbfa2" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Keycloak realms (Part -2)]]></title>
            <link>https://medium.com/@gauravswarankar/keycloak-realms-part-2-6f8170003add?source=rss-338d813a8d58------2</link>
            <guid isPermaLink="false">https://medium.com/p/6f8170003add</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[keycloak-realm]]></category>
            <category><![CDATA[keycloak]]></category>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[realm]]></category>
            <dc:creator><![CDATA[Gaurav Swarankar]]></dc:creator>
            <pubDate>Sun, 22 Dec 2024 21:31:38 GMT</pubDate>
            <atom:updated>2024-12-22T21:31:38.745Z</atom:updated>
            <content:encoded><![CDATA[<p>configuring realms</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/362/1*XOjzBFqcqIK4yQWLM19bHg.png" /><figcaption>keycloak</figcaption></figure><p>Once we have an admin account, you can configure <strong>realms</strong> in Keycloak. A realm is a space for managing users, applications, roles, and groups, and users belong to and log into a specific realm. One Keycloak installation can handle multiple realms.</p><h3>Using the Admin Console</h3><p>To configure realms and perform other administrative tasks, you use the <strong>Keycloak Admin Console</strong>.</p><h4>Steps to Access the Admin Console:</h4><ol><li>Go to the <strong>Admin Console URL</strong> (e.g., for localhost: <a href="http://localhost:8080/admin/"><strong>http://localhost:8080/admin/</strong></a>).</li><li>Log in with the admin username and password you created earlier.</li><li>Once logged in, you can:</li></ol><ul><li>Select a realm to manage from the menu labeled <strong>Master</strong> or create a new one.</li></ul><p>In the <strong>Admin Console</strong>, there are two types of realms:</p><ol><li><strong>Master Realm</strong>: This is the default realm created when you first set up Keycloak. It contains the administrator account you created during the initial login. The <strong>Master realm</strong> is only used for creating and managing other realms in your system.</li><li><strong>Other Realms</strong>: These are realms created by an administrator within the <strong>Master realm</strong>. They are used to manage users and applications for your organization. Each realm can have its own set of users, roles, and applications, and applications are owned by the users within those realms.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*rkzXIVZnRA-zUnb3.png" /></figure><p>we will create a realm to manage users and assign permissions for accessing applications. When you first log in, you start in the <strong>Master realm</strong>, which is the top-level realm. From there, you can create other realms to organize and manage users and applications.</p><ol><li>Click <strong>Keycloak</strong> next to <strong>master realm</strong>, then click <strong>Create Realm</strong>.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/902/0*J0mggP17YL2VKetY.png" /></figure><p>2. Enter a name for the realm.</p><p>3. Click <strong>Create</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/656/0*T22Sahu6ZzIVqOk9.png" /></figure><p>The current realm is now set to the realm we just created.</p><h3>Configuring SSL for a realm</h3><p><strong>SSL (Secure Socket Layer)</strong> is a protocol used to encrypt data transmitted between a server and a client, ensuring that the communication remains secure. In the context of <strong>Keycloak</strong> and its <strong>realms</strong>, <strong>configuring SSL</strong> ensures that all communication between users and Keycloak (e.g., login, user management, and accessing protected applications) is encrypted and secure.</p><h3>Why SSL is Important for a Realm</h3><p>SSL encryption helps in protecting sensitive information such as passwords, user data, and authentication tokens from being intercepted during transmission. This is especially critical when Keycloak is used for authentication and authorization in production environments, as the data being exchanged could be highly sensitive.</p><p><strong>SSL encryption ensures:</strong></p><ol><li><strong>Data Privacy:</strong> All data between clients and the Keycloak server is encrypted, making it difficult for attackers to eavesdrop on communication.</li><li><strong>Data Integrity:</strong> SSL ensures that the data being transmitted is not altered or tampered with during transit.</li><li><strong>Authentication of the Server:</strong> SSL helps clients verify that they are communicating with the correct Keycloak server, preventing man-in-the-middle attacks.</li></ol><h3>How to Configure SSL for a Realm in Keycloak</h3><ol><li><strong>Obtain an SSL Certificate</strong>: To enable SSL, you need an SSL certificate, which you can either purchase from a certificate authority (CA) or generate a self-signed certificate for testing purposes.</li><li><strong>Install the Certificate on the Keycloak Server</strong>:</li></ol><ul><li>For <strong>Keycloak</strong> to serve content over HTTPS, the certificate must be installed on the Keycloak server.</li><li>You can modify the Keycloak configuration to enable HTTPS (using SSL) by updating the <strong>standalone.xml</strong> or <strong>application.properties</strong> (depending on your setup).</li><li><strong>Configure the HTTPS Settings</strong>:</li><li>In the <strong>Keycloak Admin Console</strong>, under the realm settings, you can specify whether the realm should enforce HTTPS or accept both HTTP and HTTPS connections.</li><li>You can also define the <strong>SSL redirect</strong> to ensure that users are always redirected to the HTTPS version of your site, enhancing security.</li><li><strong>Force HTTPS for Realm Communications</strong>: In your realm settings, you can choose to enforce secure connections, ensuring that all login, registration, and other communications are done over HTTPS.</li></ul><h3>What Happens If You Don’t Use SSL?</h3><p>If you don’t configure SSL for your Keycloak realm, the data exchanged between users and the Keycloak server (and between the server and applications) will be sent in plain text. This introduces several risks:</p><ol><li><strong>Data Interception</strong>: Attackers can intercept sensitive data, such as usernames, passwords, and authentication tokens, by sniffing the traffic over unencrypted channels. This is especially risky when dealing with login credentials and sensitive user information.</li><li><strong>Man-in-the-Middle Attacks</strong>: Without SSL, attackers can impersonate the Keycloak server and intercept or alter the communication between the client and the server. This could lead to unauthorized access or data corruption.</li></ol><h3>Steps to Configure SSL</h3><ol><li>Click <strong>Realm settings</strong> in the menu.</li><li>Click the <strong>General</strong> tab.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ODReAwqgAC-kKCsm10xpLQ.png" /></figure><p>We can set the <strong>Require SSL</strong> option in Keycloak to one of these modes:</p><ol><li><strong>External requests</strong>: Keycloak allows non-SSL access only from private IP addresses (like localhost or local network addresses). If you try to access Keycloak from a public IP without SSL, you’ll get an error.</li><li><strong>None</strong>: Keycloak does not require SSL. This is typically used for development or testing when you don’t need secure connections.</li><li><strong>All requests</strong>: Keycloak requires SSL for all IP addresses, ensuring that all communication is encrypted.</li></ol><h3>Configure Email for realm</h3><p>To configure email for a realm in Keycloak, you need to set up the SMTP server settings. This allows Keycloak to send emails for various purposes like verifying email addresses, password recovery, or notifying administrators about server events. By providing the SMTP server details, you enable Keycloak to send those emails to users.</p><p>For example, you would configure the SMTP settings to connect to your email server, specify the sender’s email address, and ensure that the email delivery process is secure and functional.</p><p>Steps:</p><ol><li>Click <strong>Realm settings</strong> in the menu.</li><li>Click the <strong>Email</strong> tab.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jY3Cld1y4TQLAi7UvEOSww.png" /></figure><p>To configure email settings in Keycloak, here’s a breakdown of what each option means:</p><ol><li><strong>From</strong>: This is the email address that appears as the sender of the emails from Keycloak, such as “noreply@example.com.”</li><li><strong>From display name</strong>: This is an optional, user-friendly name that can be shown instead of the email address, like “Keycloak Support.” If not set, the plain email address will be shown.</li><li><strong>Reply to</strong>: This is the email address that will be used when someone replies to an email from Keycloak. If not set, it will default to the “From” email address.</li><li><strong>Reply to display name</strong>: Similar to the “From display name,” this is an optional, user-friendly name for the “Reply to” email address.</li><li><strong>Envelope from</strong>: This is the bounce address, or the email address that will receive undelivered emails (optional).</li></ol><h3>Connection &amp; Authentication Settings</h3><ol><li><strong>Host</strong>: This is the SMTP server address that Keycloak will use to send emails, such as “smtp.example.com.”</li><li><strong>Port</strong>: This is the port number for the SMTP server. For secure connections, you’ll typically use port 465 (SSL/TLS) or 587 (STARTTLS).</li><li><strong>Encryption</strong>: Choose whether to use SSL or TLS to secure the email sending process. SSL/TLS is recommended, especially if you’re using an external SMTP server.</li><li><strong>Authentication</strong>: If the SMTP server requires a username and password to send emails, enable this setting and provide the necessary credentials. The password can also be retrieved from a secure external vault.</li></ol><h3>Example</h3><p>For instance, if you are using Gmail’s SMTP server, you would set:</p><ul><li><strong>Host</strong>: smtp.gmail.com</li><li><strong>Port</strong>: 465 (SSL)</li><li><strong>From</strong>: noreply@example.com</li><li><strong>From display name</strong>: “Keycloak Support”</li><li><strong>Authentication</strong>: ON, with the Gmail username and app-specific password.</li></ul><p>This setup would allow Keycloak to send emails securely using Gmail’s SMTP server.</p><h3>Configure Theme</h3><p>To configure themes in Keycloak and change the appearance of the UI for a specific realm, follow these steps:</p><ol><li><strong>Go to Realm Settings</strong>: In the Keycloak Admin Console, click on the <strong>Realm Settings</strong> option in the menu.</li><li><strong>Click on the Themes Tab</strong>: Under the Realm Settings, click on the <strong>Themes</strong> tab. Here, you can choose and configure different themes for the UI elements in your realm.</li></ol><p>This allows you to customize the look and feel of pages such as the login page, error pages, and account management pages to match your organization’s branding or style.</p><ol><li>Click <strong>Realm setting</strong> in the menu.</li><li>Click the <strong>Themes</strong> tab.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-e3M7X3thGtihF0834YdDQ.png" /></figure><p>To configure themes for different UI categories in Keycloak, follow these steps:</p><ol><li><strong>Login Theme</strong>: Select the theme you want for login-related screens such as username/password entry, OTP entry, and new user registration. This affects how the login pages appear to users.</li><li><strong>Account Theme</strong>: Choose the theme for the console users will use to manage their account settings, like updating profile information or changing their password.</li><li><strong>Admin Console Theme</strong>: Pick a theme for the Keycloak Admin Console, which is used by administrators to manage realms, users, and other configurations.</li><li><strong>Email Theme</strong>: Select the theme for emails sent by Keycloak, such as password reset emails or account verification messages. The templates defined in this theme determine how the emails will look.</li></ol><p>Once you choose the desired theme for each category, click <strong>Save</strong> to apply the changes. This customizes the appearance of the different parts of Keycloak based on your preferences.</p><h3>Localization</h3><p>To enable internationalization in Keycloak and support multiple languages, follow these steps:</p><ol><li><strong>Go to Realm Settings</strong>: In the Keycloak Admin Console, click on <strong>Realm Settings</strong> in the menu.</li><li><strong>Click the Localization Tab</strong>: In the Realm Settings, click on the <strong>Localization</strong> tab.</li><li><strong>Enable Internationalization</strong>: Toggle the option to <strong>Enable Internationalization</strong>. This will allow you to support multiple languages in your realm.</li><li><strong>Select Supported Languages</strong>: Choose the languages you want to support for your UI screens. You can select multiple languages, and users will see Keycloak in their preferred language.</li></ol><p>Once you save these settings, Keycloak will present the UI in the default or selected language based on user preferences. This makes the application accessible to a wider audience by supporting different languages.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FAReEWAdoU9RYdcP1oDGbA.png" /></figure><p>Once you enable internationalization in Keycloak and select the supported languages, users can choose their preferred language the next time they log in. Here’s how it works:</p><ol><li><strong>User Login Page</strong>: When a user navigates to the login page, they will see a language selection option (like a dropdown or a language switcher). This allows them to choose the language they want to use for the login screens.</li><li><strong>Account Console and Admin Console</strong>: After logging in, the selected language will also apply to the <strong>Account Console</strong> (where users manage their account settings) and <strong>Admin Console</strong> (for administrators managing the Keycloak server).</li></ol><h3>Summary:</h3><p>We have configured Keycloak by setting up a realm, enabling themes, configuring email settings, and enabling internationalization (i18n) for a better user experience. First, we created and managed a realm where we could define users, roles, and applications. We then customized the appearance of Keycloak by selecting different themes for the login page, account console, admin console, and email templates. Additionally, we configured email settings to enable Keycloak to send verification and recovery emails by specifying SMTP server details. Finally, we enabled internationalization in the realm, allowing users to choose their preferred language during login.</p><p>Hope you enjoyed this article!</p><p>Clap 👏 If this article helps you.</p><p>See you all again soon!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6f8170003add" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Keycloak Basics (Part -1)]]></title>
            <link>https://medium.com/@gauravswarankar/keycloak-basics-part-1-8f71da77f473?source=rss-338d813a8d58------2</link>
            <guid isPermaLink="false">https://medium.com/p/8f71da77f473</guid>
            <category><![CDATA[keycloak]]></category>
            <category><![CDATA[keycloakjs]]></category>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[fastify]]></category>
            <category><![CDATA[keycloak-integration]]></category>
            <dc:creator><![CDATA[Gaurav Swarankar]]></dc:creator>
            <pubDate>Sat, 21 Dec 2024 20:57:35 GMT</pubDate>
            <atom:updated>2024-12-21T20:57:35.208Z</atom:updated>
            <content:encoded><![CDATA[<p>Keycloak is a single sign on solution for web apps and RESTful web services.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*4vQm4CjYuj30hDLk.jpg" /></figure><p><strong>Keycloak</strong> is a tool that makes it super easy for developers to add <strong>security features</strong> to their apps. Instead of coding everything from scratch, Keycloak gives you ready-made features for things like:</p><ul><li><strong>Logging in</strong> and <strong>signing up users</strong></li><li><strong>Managing user accounts</strong></li><li><strong>Connecting to company directories</strong> like LDAP or Active Directory</li><li><strong>Using third-party logins</strong> like Google or Facebook</li></ul><h3>Example</h3><p>Imagine you’re building an online shopping app. Without Keycloak, you’d have to write the code for:</p><ol><li><strong>User Login</strong> — Setting up forms, storing passwords securely, etc.</li><li><strong>Social Login</strong> — If users want to log in with Google, you’d need to handle Google’s authentication process.</li><li><strong>Password Management</strong> — Adding features like “Forgot Password” and “Change Password.”</li></ol><p>With Keycloak:</p><ol><li>Users see a customizable <strong>login screen</strong> provided by Keycloak.</li><li>If they want to sign in using Google or Facebook, Keycloak takes care of all the technical stuff for you.</li><li>Keycloak can even integrate with your company’s <strong>LDAP directory</strong> so employees can log in using their work accounts.</li></ol><p>In short, Keycloak saves time and effort by providing all these security features out of the box while letting you tweak them to fit your app!</p><h3>How KeyCloak Works:</h3><p>Keycloak is like a security guard for your apps. It’s a separate server that handles user authentication and authorization. Here’s how it works:</p><ol><li><strong>Apps Point to Keycloak</strong><br>Your app (e.g., an online store or dashboard) connects to Keycloak for security. Keycloak uses standard protocols like <strong>OpenID Connect</strong> and <strong>SAML 2.0</strong> to ensure secure communication.</li><li>When a user wants to log in:</li><li>The app redirects the user to Keycloak’s login page.</li><li>The user enters their credentials (like username and password).</li><li>Keycloak handles the login process and ensures the credentials are never seen by your app.</li><li>Once the user is authenticated, Keycloak gives the app a <strong>token</strong> (like a digital badge). This token is:</li></ol><ul><li><strong>Cryptographically signed</strong> to prevent tampering.</li><li>Includes user information (e.g., username, email, roles).</li><li>Can also include permissions (e.g., what the user can or cannot do).</li></ul><p>7.<strong> Using the Token</strong></p><ul><li>The app can use this token to personalize the user experience (e.g., showing their name).</li><li>If the app needs to call a secure backend service (like fetching user orders), it sends the token along. The backend checks the token to verify the user and their permissions.</li></ul><h3>Core Concepts of Keycloak</h3><ol><li><strong>Users</strong><br>Users are the people who log in to your app. They have details like email, username, or phone number and can belong to groups or have roles (e.g., Admin, Employee).</li><li><strong>Authentication</strong><br>This is the process of confirming <strong>who</strong> the user is (e.g., entering a password).</li><li><strong>Authorization</strong><br>This is about deciding <strong>what</strong> the user is allowed to do (e.g., access admin features).</li><li><strong>Credentials</strong><br>Data used for authentication, like passwords, OTPs, or fingerprints.</li><li><strong>Roles</strong><br>Categories for users (e.g., Admin, Manager) that define their permissions.</li><li><strong>User Role Mapping</strong><br>Connecting a user to one or more roles. For example, assigning the “Manager” role to a user gives them permissions linked to that role.</li><li><strong>Composite Roles</strong><br>A role that combines other roles. For instance, a “Superuser” role could include both “Admin” and “Manager” roles.</li><li><strong>Groups</strong><br>Collections of users with shared attributes or roles. For example, all “Marketing Team” members can inherit common permissions.</li><li><strong>Realms</strong><br>Separate spaces in Keycloak for managing users, roles, and groups. Each realm is independent (like having separate security zones for different apps).</li><li><strong>Clients</strong><br>Applications or services that use Keycloak to authenticate users. For example, your web app or mobile app is a client.</li><li><strong>Client Adapters</strong><br>Plugins that help your app work with Keycloak.</li><li><strong>Consent</strong><br>Asking users for permission before sharing their data with an app. For example, showing what info (like email) an app will access.</li><li><strong>Client Scopes</strong><br>Predefined settings for clients to simplify configurations.</li><li><strong>Identity Token</strong><br>A token with user information (like name and email) given to an app after login.</li><li><strong>Access Token</strong><br>A token that allows an app to access resources securely (e.g., fetch user data).</li><li><strong>Service Account</strong><br>A built-in account for clients to obtain tokens.</li><li><strong>Protocol Mappers</strong><br>Rules for customizing what user info is included in tokens (like email or roles).</li><li><strong>User Federation Provider</strong><br>Connect Keycloak to existing user directories like LDAP or Active Directory.</li><li><strong>Identity Provider (IDP)</strong><br>A service that authenticates users (e.g., Facebook or Google). Keycloak can also act as an IDP.</li><li><strong>Identity Provider Federation</strong><br>Keycloak can delegate authentication to external IDPs, like enabling social logins.</li><li><strong>Required Actions</strong><br>Actions users must complete during login, like resetting a password.</li><li><strong>Authentication Flows</strong><br>Steps a user follows to log in or register (e.g., entering a password and completing CAPTCHA).</li><li><strong>Events</strong><br>Logs that track what happens in Keycloak (e.g., user login attempts).</li><li><strong>Themes</strong><br>Customizable templates and styles for Keycloak screens, like login or registration pages.</li></ol><h3>Example</h3><p>In a company:</p><ul><li><strong>Users</strong> are employees.</li><li><strong>Roles</strong> like “Admin” allow access to sensitive features.</li><li><strong>Groups</strong> like “HR” or “IT” manage permissions collectively.</li><li>Keycloak connects to the company’s <strong>LDAP</strong> for login and delegates social login to Google for external partners.</li><li>Apps use <strong>tokens</strong> to securely access resources without storing passwords directly.</li></ul><h3>Installing Keycloak:</h3><ol><li>Download Keycloak setup file from the <a href="https://www.keycloak.org/downloads">official website.</a></li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8jD5BlRpZz04fIFvEScxeg.png" /></figure><p>2. Open bin folder:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/846/1*Hb8AzkuU8Cmrs_l8x5IaWg.png" /></figure><p>3. Navigate your terminal to bin folder of keycloak. (Make sure you are running terminal as an administrator) &amp; run<em> .\kc.bat (Window Batch File)</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/967/1*_eBQ4RGObta-PlnUIMNogg.png" /></figure><p>4. You will get some commands to run:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/805/1*yLTYkOZKabohfY81DoqfwQ.png" /></figure><p>5. Now run .\kc.bat start-dev to run dev server.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hEVdheUfXYpII3d-ybuA1A.png" /></figure><p>Now your Keycloak server is running.</p><p>6. After setup we will create first administrator account. After installing Keycloak, we need to create an admin account. This account has full control to manage everything in Keycloak. Using this account, you can:</p><ul><li>Log in to the Keycloak Admin Console.</li><li>Set up realms (security zones).</li><li>Add users.</li><li>Register applications to secure them with Keycloak.</li></ul><p>To access Keycloak:</p><p>* Open a web browser and go to <a href="http://localhost:8080/"><strong>http://localhost:8080</strong></a>.</p><p>* Enter a username and password that you can easily remember for future use.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fEDrvtmTY-65whhEjpz9Eg.png" /></figure><p>Once you create user you got confirmation.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/828/1*0Kpj8XLz1J_W51ehAaQTvQ.png" /></figure><p>Now Open Adminstration console. you will see something like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BvaaC0TRu0kkfMPh63Pqpg.png" /></figure><p>If you need to create the admin account remotely or via the command line, follow these steps:</p><ol><li>Set up environment variables for the admin account by running:</li></ol><pre>export KC_BOOTSTRAP_ADMIN_USERNAME=&lt;username&gt;<br>export KC_BOOTSTRAP_ADMIN_PASSWORD=&lt;password&gt;</pre><ul><li>Replace &lt;username&gt; and &lt;password&gt; with the desired admin credentials.</li></ul><p>2. Start Keycloak using the appropriate command for your system:</p><pre>bin\kc.bat start</pre><p>This will create the initial admin account that you can use to log in to the Keycloak Admin Console.</p><h3>Summary :</h3><p>We set up Keycloak by first installing it on the system and creating an admin account with full permissions to manage the platform. This was done either through the browser at <a href="http://localhost:8080/"><strong>http://localhost:8080</strong></a> or by using environment variables and starting Keycloak via the command line.</p><p>Once the admin account was created, we started the Keycloak server using the appropriate command (kc.sh or kc.bat) to initialize it. With the setup complete, Keycloak is now ready for managing users, realms, and securing applications.</p><p>Hope you enjoyed this article!</p><p>Clap 👏 If this article helps you.</p><p>See you all again soon!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8f71da77f473" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[KeyCloak]]></title>
            <link>https://medium.com/@gauravswarankar/keycloak-c525708fae23?source=rss-338d813a8d58------2</link>
            <guid isPermaLink="false">https://medium.com/p/c525708fae23</guid>
            <category><![CDATA[keycloak]]></category>
            <category><![CDATA[authentication]]></category>
            <category><![CDATA[keycloakjs]]></category>
            <category><![CDATA[fastify]]></category>
            <category><![CDATA[keycloak-integration]]></category>
            <dc:creator><![CDATA[Gaurav Swarankar]]></dc:creator>
            <pubDate>Fri, 20 Dec 2024 04:16:16 GMT</pubDate>
            <atom:updated>2024-12-20T04:16:16.867Z</atom:updated>
            <content:encoded><![CDATA[<p>Add authentication to applications and secure services with minimum effort. Keycloak provides user federation, strong authentication, user management, fine-grained authorization, and more.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*EXhyf3F9osCGWldY.png" /></figure><h3>What is Keycloak?</h3><p>Keycloak is an open-source identity and access management (IAM) solution. <strong>Open-source identity and access management (IAM) solution</strong> refers to a software platform that is manages User identities, which include details like usernames, passwords, email addresses, roles, and more.</p><ul><li><strong>Example</strong>: When you log into a website using your email and password, the platform managing your credentials is handling identity management.</li></ul><p>whereas access management controls what authenticated users are allowed to do once their identity is verified.</p><ul><li><strong>Example</strong>: A system admin can access sensitive admin dashboards, but a regular user cannot. This restriction is enforced by access management.</li></ul><p><strong>It provides features such as:</strong></p><ul><li><strong>User Authentication</strong>: Supports login via username/password, social logins, or Single Sign-On (SSO) using SAML or OpenID Connect.</li><li><strong>Authorization</strong>: Role-based and attribute-based access control for securing applications.</li><li><strong>Admin Console</strong>: Allows managing users, roles, and permissions.</li><li><strong>Token Management</strong>: Issues and validates JSON Web Tokens (JWT) to secure communication between applications and services.</li></ul><h3>IAM Solution</h3><ul><li><strong>Identity and Access Management (IAM)</strong>: A system that combines both identity and access management.</li><li><strong>Authentication</strong>: Validates a user’s identity.</li><li><strong>Authorization</strong>: Determines what resources the authenticated user is allowed to access.</li><li><strong>Single Sign-On (SSO)</strong>: Lets users log in once to access multiple systems or services.</li><li><strong>Role-Based Access Control (RBAC)</strong>: Assigns permissions based on user roles.</li><li><strong>Federated Identity</strong>: Allows integration with external identity providers (e.g., Google, Facebook).</li><li><strong>Session Management</strong>: Monitors and manages user sessions for enhanced security.</li></ul><h3>Examples of IAM Use Cases</h3><ol><li><strong>E-commerce</strong>:</li></ol><ul><li>Manage millions of users with different roles (buyers, sellers, admins).</li><li>Use social login (Google, Facebook) for quick user authentication.</li></ul><p><strong>2. Corporate Applications</strong>:</p><ul><li>Enable employees to log in to multiple tools with a single account (SSO).</li><li>Assign different permissions based on roles (e.g., HR, Finance, IT).</li></ul><p><strong>3. APIs</strong>:</p><ul><li>Secure APIs by issuing and verifying tokens (e.g., for mobile apps accessing backend services).</li></ul><p>Keycloak as an open-source IAM solution makes it easy to handle all these scenarios efficiently and securely.</p><p>Keycloak is commonly used to secure modern applications (web, mobile, APIs) and provides SDKs and adapters for integration with various frameworks.</p><h3>Implementing Keycloak with Fastify and TypeScript</h3><p>To secure a Fastify application using Keycloak, we’ll use the fastify-keycloak-adapter package.</p><pre>npm install fastify fastify-keycloak-adapter</pre><h3>What You Need Before Implementing Keycloak</h3><p>Before integrating Keycloak into your Fastify application, you need to set up a few essential configurations and gather specific information. Here’s a detailed breakdown of the prerequisites:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/902/1*J4vdPBaYyr8R-biqyz-Msg.png" /></figure><h3>Environment Variables Example</h3><p>Set up a .env file to store sensitive data:</p><pre>APP_ORIGIN=http://localhost:8888<br>KEYCLOAK_SERVER_URL=http://localhost:8080/realms/my-realm<br>KEYCLOAK_CLIENT_ID=client01<br>KEYCLOAK_CLIENT_SECRET=client01secret</pre><p><strong>So we are using </strong><strong>bypassFn for Route Security.</strong></p><p>Using bypassFn in KeycloakOptions allows you to define custom logic to bypass Keycloak protection for specific routes. Here&#39;s a step-by-step explanation and implementation:</p><h3>1. Define Unprotected Routes in securityUtils.ts</h3><p>You create a list of unprotected routes, specifying their URL, HTTP method, and optionally query parameters. For example:</p><pre>export const unProtectedRoutes: { <br>  url: string; <br>  method: string; <br>  queryParams?: Record&lt;string, string&gt;; <br>}[] = [<br>  { url: &#39;/public&#39;, method: &#39;GET&#39; }, <br>  { url: &#39;/health&#39;, method: &#39;GET&#39; }, <br>  { url: &#39;/status&#39;, method: &#39;GET&#39;, queryParams: { detail: &#39;basic&#39; } },<br>];</pre><h3>2. Handle Route Security Logic</h3><p>handleRouteSecurity checks if a request matches any of the defined unprotected routes. If it does, the route is bypassed, and Keycloak authentication is skipped.</p><pre>import { FastifyRequest } from &#39;fastify&#39;;<br>import { unProtectedRoutes } from &#39;./securityUtils&#39;;<br><br>export const handleRouteSecurity = (request: FastifyRequest): boolean =&gt; {<br>  const query = (request.query as Record&lt;string, string&gt;) || {};<br><br>  return unProtectedRoutes.some((route) =&gt; {<br>    const isUrlMatch = route.url === request.routerPath;<br>    const isMethodMatch = route.method === request.method;<br><br>    if (isUrlMatch &amp;&amp; isMethodMatch) {<br>      const isQueryParamsMatch =<br>        !route.queryParams || JSON.stringify(route.queryParams) === JSON.stringify(query);<br>      return isQueryParamsMatch;<br>    }<br><br>    return false;<br>  });<br>};</pre><ul><li><strong>URL Match</strong>: Compares the request’s URL (request.routerPath) to the route&#39;s url.</li><li><strong>Method Match</strong>: Compares the request’s method (request.method) to the route&#39;s method.</li><li><strong>Query Params Match</strong>: Optionally checks if query parameters match for the route.</li></ul><p><strong>Now go to your main file.</strong></p><pre>import fastify from &#39;fastify&#39;;<br>import keycloak, { KeycloakOptions } from &#39;fastify-keycloak-adapter&#39;;<br><br>const server = fastify();<br><br>// Environment variables<br>const opts: KeycloakOptions = {<br>  appOrigin: process.env.APP_ORIGIN as string, // Example: &#39;http://localhost:8888&#39;<br>  keycloakSubdomain: process.env.KEYCLOAK_SERVER_URL as string, // Example: &#39;http://localhost:8080/realms/my-realm&#39;<br>  clientId: process.env.KEYCLOAK_CLIENT_ID as string, // Example: &#39;client01&#39;<br>  clientSecret: process.env.KEYCLOAK_CLIENT_SECRET as string, // Client secret from Keycloak<br>  bypassFn: (req) =&gt; handleRouteSecurity(req), // Optional: Define logic to bypass routes<br>};<br><br>// Register Keycloak plugin<br>server.register(keycloak, opts);<br><br>// Protected Route<br>server.get(&#39;/protected&#39;, { preValidation: server.keycloak.protect() }, async (request, reply) =&gt; {<br>  return {<br>    message: &#39;Access granted to protected route!&#39;,<br>    user: request.keycloak,<br>  };<br>});<br><br>// Public Route<br>server.get(&#39;/public&#39;, async (request, reply) =&gt; {<br>  return { message: &#39;This is a public route.&#39; };<br>});<br><br>// Start Server<br>server.listen({ port: 8888 }, (err, address) =&gt; {<br>  if (err) {<br>    console.error(err);<br>    process.exit(1);<br>  }<br>  console.log(`Server running at ${address}`);<br>});</pre><p>By default if token is not valid we will get unauthorised message in postman response. If you want to show custom message we will use unauthorizedHandler.</p><pre>  const opts: KeycloakOptions = {<br>    appOrigin: process.env.APP_ORIGIN as string,<br>    keycloakSubdomain: process.env.KEYCLOAK_SERVER_URL as string,<br>    clientId: process.env.KEYCLOAK_CLIENT_ID as string,<br>    clientSecret: process.env.KEYCLOAK_CLIENT_SECRET as string,<br>    bypassFn: (req) =&gt; handleRouteSecurity(req),<br>    unauthorizedHandler: (request, reply) =&gt; {<br>      reply.status(401).send({<br>        statusCode: 401,<br>        error: &quot;Unauthorized&quot;,<br>        message: &quot;Access denied. You are not authorized to perform this action.&quot;,<br>      });<br>    },<br>  };</pre><h3>Testing</h3><h4>1. Run the Server</h4><p>Start the Fastify server:</p><pre>node index.js</pre><h4>2. Test with Postman</h4><ul><li><strong>Protected Route (</strong><strong>/protected)</strong>:</li><li>Send a request with a valid JWT from Keycloak.</li><li>Response: Access granted to protected route!.</li><li><strong>Public Route (</strong><strong>/public)</strong>:</li><li>No authentication needed.</li><li>Response: This is a public route.</li></ul><h3>Conclusion</h3><p>This setup ensures a secure and flexible integration between <strong>Keycloak</strong> and <strong>Fastify</strong>, supporting modern authentication and access management requirements.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c525708fae23" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>