{"id":20443,"date":"2022-02-25T17:24:25","date_gmt":"2022-02-25T16:24:25","guid":{"rendered":"https:\/\/blog.trifork.com\/?p=20443"},"modified":"2022-02-25T17:24:25","modified_gmt":"2022-02-25T16:24:25","slug":"getting-out-of-a-codependent-relationship-or-how-i-moved-to-a-healthy-component-based-spring-security-configuration","status":"publish","type":"post","link":"https:\/\/trifork.nl\/blog\/getting-out-of-a-codependent-relationship-or-how-i-moved-to-a-healthy-component-based-spring-security-configuration\/","title":{"rendered":"Getting out of a codependent relationship, or: how I moved to a healthy component-based Spring Security configuration"},"content":{"rendered":"\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"535\" src=\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Post-Image-1-1-1024x535.png\" alt=\"Holding Hands Together\" class=\"wp-image-20459\" srcset=\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Post-Image-1-1-1024x535.png 1024w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Post-Image-1-1-300x157.png 300w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Post-Image-1-1-768x401.png 768w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Post-Image-1-1-1536x802.png 1536w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Post-Image-1-1-2048x1070.png 2048w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Post-Image-1-1-1920x1003.png 1920w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>In a recent <a rel=\"noreferrer noopener\" aria-label=\"blog post (opens in a new tab)\" href=\"https:\/\/spring.io\/blog\/2022\/02\/21\/spring-security-without-the-websecurityconfigureradapter\" target=\"_blank\">blog post<\/a>, the Spring Security team announced that they\u2019ll be deprecating the configuration setup where you subclass the <tt>WebSecurityConfigurerAdapter<\/tt>. Instead, you simply define beans that allow you to set up the <tt>SecurityFilterChain<\/tt> by calling methods on the <tt>HttpSecurity<\/tt> object, and configure the <tt>WebSecurity<\/tt> object using a configurer.<\/p>\n\n\n\n<p>These options have been available for a while, but if you had a working configuration then there wasn\u2019t really a compelling need to rewrite your configuration. With the announcement that your configuration will eventually stop working, there\u2019s an actual incentive.&nbsp;<\/p>\n\n\n\n<p>Therefore I tried to update the configuration for my current project, culminating in this blog.&nbsp;<br \/><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">A Love Triangle<\/h2>\n\n\n\n<p>Our configuration defines a custom <tt>AuthenticationProvider<\/tt>, which knows how to accept a custom JWT Bearer token and then checks that against one of two configured AWS Cognito identity providers, as we have a dual region setup running on AWS (I might once write a separate blog post on our Cognito setup and Spring Security; ping me if you\u2019re interested).&nbsp;<br \/>This is accompanied by a custom authentication filter, which creates a custom <tt>Authentication<\/tt> token holding the JWT and passes that to the provider via the <tt>AuthenticationManager<\/tt>. <\/p>\n\n\n\n<p>This is quite a common setup if you want to extend the framework with your own custom authentication mechanism: the idea is that the filter only knows how to create the <tt>Authentication<\/tt> token, and it\u2019s the <tt>AuthenticationProvider<\/tt> that uses that token to come up with an <tt>Authentication<\/tt> object that represents an authenticated principal by using the provided info to perform the actual authentication.  <\/p>\n\n\n\n<p>In short, that means that:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>The provider needs to be registered with the <tt>AuthenticationManager<\/tt><\/li><li>Our filter needs to be injected with the <tt>AuthenticationManager<\/tt><\/li><li>The filter needs to be inserted into the <tt>SecurityFilterChain<\/tt><\/li><li>Only after that chain has been created, the <tt>AuthenticationManager<\/tt> is created<\/li><\/ul>\n\n\n\n<p>Ouch\u2026 We\u2019re running into an unhealthy chain of dependencies here for our filter.&nbsp;So how do we untangle this unfortunate triangle?<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Some Method That I Used To Know<\/h2>\n\n\n\n<p>In the situation where you extend the <tt>WebSecurityConfigurerAdapter<\/tt>, this problem is solved by providing you with an <tt>authenticationManagerBean<\/tt> method. It returns what\u2019s effectively a lazy-loading proxy to the real <tt>AuthenticationManager<\/tt>, so you can inject that into your filter before the real manager has been created. <br \/>The typical way to use it is to override it so that you can annotate it with <tt>@Bean<\/tt>:&nbsp;<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; gutter: false; title: ; notranslate\" title=\"\">\n@Bean(name = \"authenticationManager\")\n@Override\npublic AuthenticationManager authenticationManagerBean() throws Exception {\n   return super.authenticationManagerBean();\n}\n<\/pre><\/div>\n\n\n<p>Now the <tt>AuthenticationManager<\/tt> is simply available as a bean that can be dependency injected.<br \/><\/p>\n\n\n\n<p>However, with the component-based setup there are no helper methods like that anymore. It wasn\u2019t obvious to me how to address this, so I set out to try some options.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Relationship Experiments<\/h2>\n\n\n\n<p>One of the first things I tried, after looking at how Spring Security itself deals with some of these issues, was to inject the <tt>HttpSecurity<\/tt> into the <tt>@Bean<\/tt> method that created the filter so that I could call <tt>httpSecurity.getSharedObject(AuthenticationManager.class)<\/tt> to obtain the <tt>AuthenticationManager<\/tt>, allowing me to pass it to the filter.<br \/>However, when that bean method is called that manager isn\u2019t created yet, so that code simply returns null.<\/p>\n\n\n\n<p>I experimented with some other setups as well, many of them actually resulting in a circular dependency from the configuration class on itself, preventing our Spring Boot services from starting up (this is <a href=\"https:\/\/github.com\/spring-projects\/spring-boot\/wiki\/Spring-Boot-2.6-Release-Notes#circular-references-prohibited-by-default\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"not allowed by default since Spring Boot 2.6 (opens in a new tab)\">not allowed by default since Spring Boot 2.6<\/a>). <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Happily Ever After?<\/h2>\n\n\n\n<p>After some further investigation I understood that Spring Security is still providing an <tt>AuthenticationManagerBuilder<\/tt> bean that you can use for configuration, which eventually creates the <tt>AuthenticationManager<\/tt> that we\u2019re looking for.<\/p>\n\n\n\n<p>For configuration purposes, you can autowire it in your config class, but you have to ensure that your class is annotated with <tt>@EnableGlobalAuthentication<\/tt>: either directly, or by using another annotation that has this as a meta-annotation. For example, this is how we can register our custom provider:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; gutter: false; title: ; notranslate\" title=\"\">\n@Autowired\nvoid registerProvider(AuthenticationManagerBuilder builder) {\n   builder.authenticationProvider(new CognitoJwtAuthProvider());\n}\n<\/pre><\/div>\n\n\n<p>I figured the builder would let me access the manager that it eventually builds, but of course by the time that all this configuration is still taking place that hasn\u2019t happened yet. Spring does make it easy for components to receive a callback when the context is completely created \/ refreshed using the <tt>SmartInitializingSingleton<\/tt> interface, so eventually this is what I ended up with.<br \/>In our configuration class:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; gutter: false; title: ; notranslate\" title=\"\">\n@Bean\nJwtAuthenticationFilter jwtAuthFilter(AuthenticationManagerBuilder builder) {\n   return new JwtAuthenticationFilter(builder);\n}\n<\/pre><\/div>\n\n\n<p>In the filter class:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; gutter: false; title: ; notranslate\" title=\"\">\npublic class JwtAuthenticationFilter extends OncePerRequestFilter\n                                     implements SmartInitializingSingleton\n{\n   private AuthenticationManagerBuilder authMgrBuilder;\n   private AuthenticationManager authenticationManager;\n\n   public JwtAuthenticationFilter(AuthenticationManagerBuilder authMgrBuilder) {\n       this.authMgrBuilder = authMgrBuilder;\n   }\n\n   @Override\n   public void afterSingletonsInstantiated() {\n       this.authenticationManager = authMgrBuilder.getObject();\n   }\n\u2026\n}\n<\/pre><\/div>\n\n\n<p>This does the trick, but it feels pretty awkward to set up your filter this way. I had a look at how Spring Security typically does this for its own filters: that involves additional <tt>SecurityConfigurer<\/tt> implementations that can set the <tt>AuthenticationManager<\/tt> on the filter once it becomes available, thus managing the instantiation of the filter in different steps. I don\u2019t need \/ want to write such a configurer just for this purpose, so for now I guess I\u2019ll stick to this.<\/p>\n\n\n\n<p>If you\u2019re in a similar situation with a custom filter that needs the <tt>AuthenticationManager<\/tt>, I would like to hear about better approaches. <br \/>Please leave a comment if you came up with something; after all, I\u2019m not married to my current code \ud83d\ude09<br \/><\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/bit.ly\/33oCsQ6\" target=\"_blank\" rel=\"noreferrer noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"256\" src=\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png\" alt=\"\" class=\"wp-image-20303\" srcset=\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png 1024w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-300x75.png 300w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-768x192.png 768w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1536x384.png 1536w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-2048x512.png 2048w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1920x480.png 1920w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>In a recent blog post, the Spring Security team announced that they\u2019ll be deprecating the configuration setup where you subclass the WebSecurityConfigurerAdapter. Instead, you simply define beans that allow you to set up the SecurityFilterChain by calling methods on the HttpSecurity object, and configure the WebSecurity object using a configurer. These options have been available [&hellip;]<\/p>\n","protected":false},"author":62,"featured_media":20459,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"content-type":"","footnotes":""},"categories":[337,94],"tags":[],"class_list":["post-20443","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-from-the-trenches","category-spring"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Getting out of a codependent relationship, or: how I moved to a healthy component-based Spring Security configuration - Trifork Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/trifork.nl\/blog\/getting-out-of-a-codependent-relationship-or-how-i-moved-to-a-healthy-component-based-spring-security-configuration\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Getting out of a codependent relationship, or: how I moved to a healthy component-based Spring Security configuration - Trifork Blog\" \/>\n<meta property=\"og:description\" content=\"In a recent blog post, the Spring Security team announced that they\u2019ll be deprecating the configuration setup where you subclass the WebSecurityConfigurerAdapter. Instead, you simply define beans that allow you to set up the SecurityFilterChain by calling methods on the HttpSecurity object, and configure the WebSecurity object using a configurer. These options have been available [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/trifork.nl\/blog\/getting-out-of-a-codependent-relationship-or-how-i-moved-to-a-healthy-component-based-spring-security-configuration\/\" \/>\n<meta property=\"og:site_name\" content=\"Trifork Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-02-25T16:24:25+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Post-Image-1-1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"3920\" \/>\n\t<meta property=\"og:image:height\" content=\"2048\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Joris Kuipers\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Joris Kuipers\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/trifork.nl\/blog\/getting-out-of-a-codependent-relationship-or-how-i-moved-to-a-healthy-component-based-spring-security-configuration\/\",\"url\":\"https:\/\/trifork.nl\/blog\/getting-out-of-a-codependent-relationship-or-how-i-moved-to-a-healthy-component-based-spring-security-configuration\/\",\"name\":\"Getting out of a codependent relationship, or: how I moved to a healthy component-based Spring Security configuration - Trifork Blog\",\"isPartOf\":{\"@id\":\"https:\/\/trifork.nl\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/trifork.nl\/blog\/getting-out-of-a-codependent-relationship-or-how-i-moved-to-a-healthy-component-based-spring-security-configuration\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/trifork.nl\/blog\/getting-out-of-a-codependent-relationship-or-how-i-moved-to-a-healthy-component-based-spring-security-configuration\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Post-Image-1-1.png\",\"datePublished\":\"2022-02-25T16:24:25+00:00\",\"author\":{\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/265bd41e503f7176742258a927de598b\"},\"breadcrumb\":{\"@id\":\"https:\/\/trifork.nl\/blog\/getting-out-of-a-codependent-relationship-or-how-i-moved-to-a-healthy-component-based-spring-security-configuration\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/trifork.nl\/blog\/getting-out-of-a-codependent-relationship-or-how-i-moved-to-a-healthy-component-based-spring-security-configuration\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/trifork.nl\/blog\/getting-out-of-a-codependent-relationship-or-how-i-moved-to-a-healthy-component-based-spring-security-configuration\/#primaryimage\",\"url\":\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Post-Image-1-1.png\",\"contentUrl\":\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Post-Image-1-1.png\",\"width\":3920,\"height\":2048,\"caption\":\"Holding Hands Together\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/trifork.nl\/blog\/getting-out-of-a-codependent-relationship-or-how-i-moved-to-a-healthy-component-based-spring-security-configuration\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/trifork.nl\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Getting out of a codependent relationship, or: how I moved to a healthy component-based Spring Security configuration\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/trifork.nl\/blog\/#website\",\"url\":\"https:\/\/trifork.nl\/blog\/\",\"name\":\"Trifork Blog\",\"description\":\"Keep updated on the technical solutions Trifork is working on!\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/trifork.nl\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/265bd41e503f7176742258a927de598b\",\"name\":\"Joris Kuipers\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/9ab8da0d60582bad84342d4602d23dbd?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/9ab8da0d60582bad84342d4602d23dbd?s=96&d=mm&r=g\",\"caption\":\"Joris Kuipers\"},\"sameAs\":[\"http:\/\/www.trifork.nl\"],\"url\":\"https:\/\/trifork.nl\/blog\/author\/jorisk\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Getting out of a codependent relationship, or: how I moved to a healthy component-based Spring Security configuration - Trifork Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/trifork.nl\/blog\/getting-out-of-a-codependent-relationship-or-how-i-moved-to-a-healthy-component-based-spring-security-configuration\/","og_locale":"en_US","og_type":"article","og_title":"Getting out of a codependent relationship, or: how I moved to a healthy component-based Spring Security configuration - Trifork Blog","og_description":"In a recent blog post, the Spring Security team announced that they\u2019ll be deprecating the configuration setup where you subclass the WebSecurityConfigurerAdapter. Instead, you simply define beans that allow you to set up the SecurityFilterChain by calling methods on the HttpSecurity object, and configure the WebSecurity object using a configurer. These options have been available [&hellip;]","og_url":"https:\/\/trifork.nl\/blog\/getting-out-of-a-codependent-relationship-or-how-i-moved-to-a-healthy-component-based-spring-security-configuration\/","og_site_name":"Trifork Blog","article_published_time":"2022-02-25T16:24:25+00:00","og_image":[{"width":3920,"height":2048,"url":"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Post-Image-1-1.png","type":"image\/png"}],"author":"Joris Kuipers","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Joris Kuipers","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/trifork.nl\/blog\/getting-out-of-a-codependent-relationship-or-how-i-moved-to-a-healthy-component-based-spring-security-configuration\/","url":"https:\/\/trifork.nl\/blog\/getting-out-of-a-codependent-relationship-or-how-i-moved-to-a-healthy-component-based-spring-security-configuration\/","name":"Getting out of a codependent relationship, or: how I moved to a healthy component-based Spring Security configuration - Trifork Blog","isPartOf":{"@id":"https:\/\/trifork.nl\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/trifork.nl\/blog\/getting-out-of-a-codependent-relationship-or-how-i-moved-to-a-healthy-component-based-spring-security-configuration\/#primaryimage"},"image":{"@id":"https:\/\/trifork.nl\/blog\/getting-out-of-a-codependent-relationship-or-how-i-moved-to-a-healthy-component-based-spring-security-configuration\/#primaryimage"},"thumbnailUrl":"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Post-Image-1-1.png","datePublished":"2022-02-25T16:24:25+00:00","author":{"@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/265bd41e503f7176742258a927de598b"},"breadcrumb":{"@id":"https:\/\/trifork.nl\/blog\/getting-out-of-a-codependent-relationship-or-how-i-moved-to-a-healthy-component-based-spring-security-configuration\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/trifork.nl\/blog\/getting-out-of-a-codependent-relationship-or-how-i-moved-to-a-healthy-component-based-spring-security-configuration\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/trifork.nl\/blog\/getting-out-of-a-codependent-relationship-or-how-i-moved-to-a-healthy-component-based-spring-security-configuration\/#primaryimage","url":"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Post-Image-1-1.png","contentUrl":"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Post-Image-1-1.png","width":3920,"height":2048,"caption":"Holding Hands Together"},{"@type":"BreadcrumbList","@id":"https:\/\/trifork.nl\/blog\/getting-out-of-a-codependent-relationship-or-how-i-moved-to-a-healthy-component-based-spring-security-configuration\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/trifork.nl\/blog\/"},{"@type":"ListItem","position":2,"name":"Getting out of a codependent relationship, or: how I moved to a healthy component-based Spring Security configuration"}]},{"@type":"WebSite","@id":"https:\/\/trifork.nl\/blog\/#website","url":"https:\/\/trifork.nl\/blog\/","name":"Trifork Blog","description":"Keep updated on the technical solutions Trifork is working on!","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/trifork.nl\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/265bd41e503f7176742258a927de598b","name":"Joris Kuipers","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/9ab8da0d60582bad84342d4602d23dbd?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/9ab8da0d60582bad84342d4602d23dbd?s=96&d=mm&r=g","caption":"Joris Kuipers"},"sameAs":["http:\/\/www.trifork.nl"],"url":"https:\/\/trifork.nl\/blog\/author\/jorisk\/"}]}},"_links":{"self":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts\/20443","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/users\/62"}],"replies":[{"embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/comments?post=20443"}],"version-history":[{"count":0,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts\/20443\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/media\/20459"}],"wp:attachment":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/media?parent=20443"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/categories?post=20443"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/tags?post=20443"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}