{"id":239,"date":"2007-04-30T22:53:17","date_gmt":"2007-04-30T22:53:17","guid":{"rendered":"http:\/\/beta.robertprice.co.uk\/robblog\/2007\/04\/atom_wsse_authentication_using_c_net-shtml\/"},"modified":"2007-04-30T22:53:17","modified_gmt":"2007-04-30T22:53:17","slug":"atom_wsse_authentication_using_c_net-shtml","status":"publish","type":"post","link":"https:\/\/www.robertprice.co.uk\/robblog\/atom_wsse_authentication_using_c_net-shtml\/","title":{"rendered":"Atom WSSE Authentication Using C# .NET"},"content":{"rendered":"<p>\nI received an email asking for a hand with a C# .NET implementation of the WSSE atom authentication for Nokia&#8217;s <a href=\"http:\/\/www.nokia.com\/lifeblog\">Lifeblog<\/a>.\n<\/p>\n<p>\nI took a look at this as I&#8217;m brushing up on my C# at the moment for work, and I relish a challenge.\n<\/p>\n<p>\nAs there are two different methods of authentication depending on the version of Lifeblog being used, the code has to handle this.\n<\/p>\n<p>\nThe first method is to append the nonce, timestamp and password together, create a SHA1 hash with this and Base64 encode the result. The second way is almost the same, but the nonce has to be Base64 decoded first before being appended with the timestamp and password.\n<\/p>\n<p>\nSee my previous article on <a href=\"\/robblog\/archive\/2005\/2\/WSSE_Authentication_For_Atom_Using_Perl.shtml\">WSSE Authentication For Atom Using Perl<\/a> for more details on how this works.\n<\/p>\n<p>\nThe first method can be calculate a digest value using code like this.\n<\/p>\n<div class=\"code\"><code>string mystring = nonce + created + password;<br \/>\nSHA1Managed SHhash = new SHA1Managed();<br \/>\nstring mydigest = Convert.ToBase64String(SHhash.ComputeHash(System.Text.Encoding.ASCII.GetBytes(mystring)));<br \/>\n<\/code><\/div>\n<p>\nMy first attempt at the second method looked very similar.\n<\/p>\n<div class=\"code\"><code>string mystring = (System.Text.Encoding.ASCII.GetString(Convert.FromBase64String(nonce))) + created + password;<br \/>\nSHA1Managed SHhash = new SHA1Managed();<br \/>\nstring mydigest = Convert.ToBase64String(SHhash.ComputeHash(System.Text.Encoding.ASCII.GetBytes(mystring)));<br \/>\n<\/code><\/div>\n<p>\nLooks OK on the surface, but it fails to validate when posting from my Nokia N93 phone.\n<\/p>\n<p>\nWhat&#8217;s gone wrong?\n<\/p>\n<p>\nWell looking in the debugger, the process of converting the nonce back from the array of bytes <code>Convert.FromBase64String()<\/code> produces and appending them to form mystring corrupts the data compared with the Perl version in my previous article.\n<\/p>\n<p>\nWe know the approach is basically right, so we need to cut out this corrupting step.\n<\/p>\n<p>\nThe best way to do this is to keep the data in byte arrays as we need the data in this format anyway to computer the SHA1.\n<\/p>\n<div class=\"code\"><code><br \/>\nSystem.Text.Encoding enc = System.Text.Encoding.UTF8;<br \/>\nbyte[] noncebytes = enc.GetBytes(nonce);<br \/>\nbyte[] passwordbytes = enc.GetBytes(password);<br \/>\nbyte[] createdbytes = enc.GetBytes(created);<br \/>\nbyte[] code = new byte[nonce.Length + password.Length + created.Length];<br \/>\nArray.Copy(nonce, code, nonce.Length);<br \/>\nArray.Copy(created, 0, code, nonce.Length, created.Length);<br \/>\nArray.Copy(password, 0, code, nonce.Length + created.Length, password.Length);<br \/>\nSystem.Security.Cryptography.SHA1Managed SHhash = new System.Security.Cryptography.SHA1Managed();<br \/>\nstring digest = Convert.ToBase64String(SHhash.ComputeHash(code));<br \/>\n<\/code><\/div>\n<p>\nI&#8217;m sure there is a nicer way to achieve the appending of the 3 arrays together in C#, but this works for now.\n<\/p>\n<p>\nWe can tie this up to form a nice static class to handle our WSSE authentication.\n<\/p>\n<div class=\"code\"><code>\/\/\/ &lt;summary&gt;<br \/>\n\/\/\/ Computes WSSE codes from input for validation.<br \/>\n\/\/\/ &lt;\/summary&gt;<br \/>\npublic static class WSSE {<br \/>\n\/\/\/ &lt;summary&gt;<br \/>\n\/\/\/ Calculate the digest.<br \/>\n\/\/\/ &lt;\/summary&gt;<br \/>\n\/\/\/ &lt;param name=\"password\"&gt;A string with your unencrypted password.&lt;\/param&gt;<br \/>\n\/\/\/ &lt;param name=\"nonce\"&gt;The nonce the digest is to be created with as a string.&lt;\/param&gt;<br \/>\n\/\/\/ &lt;param name=\"created\"&gt;The timestamp as a string.&lt;\/param&gt;<br \/>\n\/\/\/ &lt;returns&gt;A string containing the digest.&lt;\/returns&gt;<br \/>\npublic static string GetDigest(string password, string nonce, string created)<br \/>\n{<br \/>\nreturn GetDigest(password, nonce, created, System.Text.Encoding.ASCII);<br \/>\n}<br \/>\n\/\/\/ &lt;summary&gt;<br \/>\n\/\/\/ Calculate the digest.<br \/>\n\/\/\/ &lt;\/summary&gt;<br \/>\n\/\/\/ &lt;param name=\"password\"&gt;A string with your unencrypted password.&lt;\/param&gt;<br \/>\n\/\/\/ &lt;param name=\"nonce\"&gt;The nonce the digest is to be created with as a string.&lt;\/param&gt;<br \/>\n\/\/\/ &lt;param name=\"created\"&gt;The timestamp as a string.&lt;\/param&gt;<br \/>\n\/\/\/ &lt;param name=\"enc\"&gt;The System.Text.Encoding to use.&lt;\/param&gt;<br \/>\n\/\/\/ &lt;returns&gt;A string containing the digest.&lt;\/returns&gt;<br \/>\npublic static string GetDigest(string password, string nonce, string created, System.Text.Encoding enc)<br \/>\n{<br \/>\nbyte[] noncebytes = enc.GetBytes(nonce);<br \/>\nbyte[] passwordbytes = enc.GetBytes(password);<br \/>\nbyte[] createdbytes = enc.GetBytes(created);<br \/>\nreturn generatecode(noncebytes, passwordbytes, createdbytes);<br \/>\n}<br \/>\n\/\/\/ &lt;summary&gt;<br \/>\n\/\/\/ Calculate the alternative digest.<br \/>\n\/\/\/ &lt;\/summary&gt;<br \/>\n\/\/\/ &lt;param name=\"password\"&gt;A string with your unencrypted password.&lt;\/param&gt;<br \/>\n\/\/\/ &lt;param name=\"nonce\"&gt;The nonce the digest is to be created with as a string.&lt;\/param&gt;<br \/>\n\/\/\/ &lt;param name=\"created\"&gt;The timestamp as a string.&lt;\/param&gt;<br \/>\n\/\/\/ &lt;returns&gt;A string containing the digest.&lt;\/returns&gt;<br \/>\npublic static string GetDigestAlt(string password, string nonce, string created)<br \/>\n{<br \/>\nreturn GetDigestAlt(password, nonce, created, System.Text.Encoding.ASCII);<br \/>\n}<br \/>\n\/\/\/ &lt;summary&gt;<br \/>\n\/\/\/ Calculate the alternative digest.<br \/>\n\/\/\/ &lt;\/summary&gt;<br \/>\n\/\/\/ &lt;param name=\"password\"&gt;A string with your unencrypted password.&lt;\/param&gt;<br \/>\n\/\/\/ &lt;param name=\"nonce\"&gt;The nonce the digest is to be created with as a string.&lt;\/param&gt;<br \/>\n\/\/\/ &lt;param name=\"created\"&gt;The timestamp as a string.&lt;\/param&gt;<br \/>\n\/\/\/ &lt;param name=\"enc\"&gt;The System.Text.Encoding to use.&lt;\/param&gt;<br \/>\n\/\/\/ &lt;returns&gt;A string containing the digest.&lt;\/returns&gt;<br \/>\npublic static string GetDigestAlt(string password, string nonce, string created, System.Text.Encoding enc)<br \/>\n{<br \/>\nbyte[] noncebytes = Convert.FromBase64String(nonce);<br \/>\nbyte[] passwordbytes = enc.GetBytes(password);<br \/>\nbyte[] createdbytes = enc.GetBytes(created);<br \/>\nreturn generatecode(noncebytes, passwordbytes, createdbytes);<br \/>\n}<br \/>\nprivate static string generatecode(byte[] nonce, byte[] password, byte[] created)<br \/>\n{<br \/>\nbyte[] code = new byte[nonce.Length + password.Length + created.Length];<br \/>\nArray.Copy(nonce, code, nonce.Length);<br \/>\nArray.Copy(created, 0, code, nonce.Length, created.Length);<br \/>\nArray.Copy(password, 0, code, nonce.Length + created.Length, password.Length);<br \/>\nSystem.Security.Cryptography.SHA1Managed SHhash = new System.Security.Cryptography.SHA1Managed();<br \/>\nreturn Convert.ToBase64String(SHhash.ComputeHash(code));<br \/>\n}<br \/>\n\/\/\/ &lt;summary&gt;<br \/>\n\/\/\/ Validates password, nonce and created create the same digest code as digest.<br \/>\n\/\/\/ &lt;\/summary&gt;<br \/>\n\/\/\/ &lt;param name=\"password\"&gt;A string with your unencrypted password.&lt;\/param&gt;<br \/>\n\/\/\/ &lt;param name=\"nonce\"&gt;The nonce the digest is to be created with as a string.&lt;\/param&gt;<br \/>\n\/\/\/ &lt;param name=\"created\"&gt;The timestamp as a string.&lt;\/param&gt;<br \/>\n\/\/\/ &lt;param name=\"digest\"&gt;The digest to validate the password, nonce and created strings against as a string.&lt;\/param&gt;<br \/>\n\/\/\/ &lt;returns&gt;true or false depending on wether the digest validates&lt;\/returns&gt;<br \/>\npublic static bool IsValid(string password, string nonce, string created, string digest)<br \/>\n{<br \/>\nreturn digest == GetDigest(password, nonce, created) || digest == GetDigestAlt(password, nonce, created);<br \/>\n}<br \/>\n\/\/\/ &lt;summary&gt;<br \/>\n\/\/\/ Validates password, nonce and created create the same digest code as digest.<br \/>\n\/\/\/ &lt;\/summary&gt;<br \/>\n\/\/\/ &lt;param name=\"password\"&gt;A string with your unencrypted password.&lt;\/param&gt;<br \/>\n\/\/\/ &lt;param name=\"nonce\"&gt;The nonce the digest is to be created with as a string.&lt;\/param&gt;<br \/>\n\/\/\/ &lt;param name=\"created\"&gt;The timestamp as a string.&lt;\/param&gt;<br \/>\n\/\/\/ &lt;param name=\"digest\"&gt;The digest to validate the password, nonce and created strings against as a string.&lt;\/param&gt;<br \/>\n\/\/\/ &lt;param name=\"enc\"&gt;A System.Text.Encoding encoding.&lt;\/param&gt;<br \/>\n\/\/\/ &lt;returns&gt;true or false depending on wether the digest validates.&lt;\/returns&gt;<br \/>\npublic static bool IsValid(string password, string nonce, string created, string digest, System.Text.Encoding enc)<br \/>\n{<br \/>\nreturn digest == GetDigest(password, nonce, created, enc) || digest == GetDigestAlt(password, nonce, created, enc);<br \/>\n}<br \/>\n}<br \/>\n<\/code><\/div>\n<p>\nWe can test the code using the following code snippet.\n<\/p>\n<div class=\"code\"><code>string digest = \"nvvHvNuLb+7wGFrop+cC2tjgQqs=\";<br \/>\nstring nonce = \"bgZ4BHcjmWcg7gVhCxyQOg==\";<br \/>\nstring timestamp = \"2006-04-25T19:40:45Z\";<br \/>\nstring password = \"a\";<br \/>\nif (WSSE.IsValid(password, nonce, timestamp, digest, System.Text.Encoding.UTF8))<br \/>\n{<br \/>\nConsole.WriteLine(\"valid\");<br \/>\n}<br \/>\nelse<br \/>\n{<br \/>\nConsole.WriteLine(\"invalid\");<br \/>\n}<br \/>\n<\/code><\/div>\n<p>\nThis gives us the result &#8220;valid&#8221; as we&#8217;d hope.\n<\/p>\n<p>\nTo save you time, feel free to download the C# code<br \/>\n<a href=\"\/robblog\/misc\/WSSE.cs\">WSSE.cs<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I received an email asking for a hand with a C# .NET implementation of the WSSE atom authentication for Nokia&#8217;s Lifeblog. I took a look at this as I&#8217;m brushing up on my C# at the moment for work, and I relish a challenge. As there are two different methods of authentication depending on the &hellip; <a href=\"https:\/\/www.robertprice.co.uk\/robblog\/atom_wsse_authentication_using_c_net-shtml\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Atom WSSE Authentication Using C# .NET&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[2],"tags":[7,35,38,45],"class_list":["post-239","post","type-post","status-publish","format-standard","hentry","category-dev","tag-net","tag-lifeblog","tag-mobile","tag-nokia"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Atom WSSE Authentication Using C# .NET - Robert Price<\/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:\/\/www.robertprice.co.uk\/robblog\/atom_wsse_authentication_using_c_net-shtml\/\" \/>\n<meta property=\"og:locale\" content=\"en_GB\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Atom WSSE Authentication Using C# .NET - Robert Price\" \/>\n<meta property=\"og:description\" content=\"I received an email asking for a hand with a C# .NET implementation of the WSSE atom authentication for Nokia&#8217;s Lifeblog. I took a look at this as I&#8217;m brushing up on my C# at the moment for work, and I relish a challenge. As there are two different methods of authentication depending on the &hellip; Continue reading &quot;Atom WSSE Authentication Using C# .NET&quot;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.robertprice.co.uk\/robblog\/atom_wsse_authentication_using_c_net-shtml\/\" \/>\n<meta property=\"og:site_name\" content=\"Robert Price\" \/>\n<meta property=\"article:published_time\" content=\"2007-04-30T22:53:17+00:00\" \/>\n<meta name=\"author\" content=\"rob\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"rob\" \/>\n\t<meta name=\"twitter:label2\" content=\"Estimated reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/atom_wsse_authentication_using_c_net-shtml\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/atom_wsse_authentication_using_c_net-shtml\\\/\"},\"author\":{\"name\":\"rob\",\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/#\\\/schema\\\/person\\\/fac6d5b076e0e14e1fb13e15b542a6c5\"},\"headline\":\"Atom WSSE Authentication Using C# .NET\",\"datePublished\":\"2007-04-30T22:53:17+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/atom_wsse_authentication_using_c_net-shtml\\\/\"},\"wordCount\":334,\"keywords\":[\".NET\",\"Lifeblog\",\"Mobile\",\"Nokia\"],\"articleSection\":[\"Dev\"],\"inLanguage\":\"en-GB\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/atom_wsse_authentication_using_c_net-shtml\\\/\",\"url\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/atom_wsse_authentication_using_c_net-shtml\\\/\",\"name\":\"Atom WSSE Authentication Using C# .NET - Robert Price\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/#website\"},\"datePublished\":\"2007-04-30T22:53:17+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/#\\\/schema\\\/person\\\/fac6d5b076e0e14e1fb13e15b542a6c5\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/atom_wsse_authentication_using_c_net-shtml\\\/#breadcrumb\"},\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/atom_wsse_authentication_using_c_net-shtml\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/atom_wsse_authentication_using_c_net-shtml\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Atom WSSE Authentication Using C# .NET\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/#website\",\"url\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/\",\"name\":\"Robert Price\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-GB\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/#\\\/schema\\\/person\\\/fac6d5b076e0e14e1fb13e15b542a6c5\",\"name\":\"rob\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/6f0eb511179100a4e968abc70403e33686e6ab3e992e392bedd2ccac01da666c?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/6f0eb511179100a4e968abc70403e33686e6ab3e992e392bedd2ccac01da666c?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/6f0eb511179100a4e968abc70403e33686e6ab3e992e392bedd2ccac01da666c?s=96&d=mm&r=g\",\"caption\":\"rob\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Atom WSSE Authentication Using C# .NET - Robert Price","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:\/\/www.robertprice.co.uk\/robblog\/atom_wsse_authentication_using_c_net-shtml\/","og_locale":"en_GB","og_type":"article","og_title":"Atom WSSE Authentication Using C# .NET - Robert Price","og_description":"I received an email asking for a hand with a C# .NET implementation of the WSSE atom authentication for Nokia&#8217;s Lifeblog. I took a look at this as I&#8217;m brushing up on my C# at the moment for work, and I relish a challenge. As there are two different methods of authentication depending on the &hellip; Continue reading \"Atom WSSE Authentication Using C# .NET\"","og_url":"https:\/\/www.robertprice.co.uk\/robblog\/atom_wsse_authentication_using_c_net-shtml\/","og_site_name":"Robert Price","article_published_time":"2007-04-30T22:53:17+00:00","author":"rob","twitter_card":"summary_large_image","twitter_misc":{"Written by":"rob","Estimated reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.robertprice.co.uk\/robblog\/atom_wsse_authentication_using_c_net-shtml\/#article","isPartOf":{"@id":"https:\/\/www.robertprice.co.uk\/robblog\/atom_wsse_authentication_using_c_net-shtml\/"},"author":{"name":"rob","@id":"https:\/\/www.robertprice.co.uk\/robblog\/#\/schema\/person\/fac6d5b076e0e14e1fb13e15b542a6c5"},"headline":"Atom WSSE Authentication Using C# .NET","datePublished":"2007-04-30T22:53:17+00:00","mainEntityOfPage":{"@id":"https:\/\/www.robertprice.co.uk\/robblog\/atom_wsse_authentication_using_c_net-shtml\/"},"wordCount":334,"keywords":[".NET","Lifeblog","Mobile","Nokia"],"articleSection":["Dev"],"inLanguage":"en-GB"},{"@type":"WebPage","@id":"https:\/\/www.robertprice.co.uk\/robblog\/atom_wsse_authentication_using_c_net-shtml\/","url":"https:\/\/www.robertprice.co.uk\/robblog\/atom_wsse_authentication_using_c_net-shtml\/","name":"Atom WSSE Authentication Using C# .NET - Robert Price","isPartOf":{"@id":"https:\/\/www.robertprice.co.uk\/robblog\/#website"},"datePublished":"2007-04-30T22:53:17+00:00","author":{"@id":"https:\/\/www.robertprice.co.uk\/robblog\/#\/schema\/person\/fac6d5b076e0e14e1fb13e15b542a6c5"},"breadcrumb":{"@id":"https:\/\/www.robertprice.co.uk\/robblog\/atom_wsse_authentication_using_c_net-shtml\/#breadcrumb"},"inLanguage":"en-GB","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.robertprice.co.uk\/robblog\/atom_wsse_authentication_using_c_net-shtml\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.robertprice.co.uk\/robblog\/atom_wsse_authentication_using_c_net-shtml\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.robertprice.co.uk\/robblog\/"},{"@type":"ListItem","position":2,"name":"Atom WSSE Authentication Using C# .NET"}]},{"@type":"WebSite","@id":"https:\/\/www.robertprice.co.uk\/robblog\/#website","url":"https:\/\/www.robertprice.co.uk\/robblog\/","name":"Robert Price","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.robertprice.co.uk\/robblog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-GB"},{"@type":"Person","@id":"https:\/\/www.robertprice.co.uk\/robblog\/#\/schema\/person\/fac6d5b076e0e14e1fb13e15b542a6c5","name":"rob","image":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/secure.gravatar.com\/avatar\/6f0eb511179100a4e968abc70403e33686e6ab3e992e392bedd2ccac01da666c?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/6f0eb511179100a4e968abc70403e33686e6ab3e992e392bedd2ccac01da666c?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/6f0eb511179100a4e968abc70403e33686e6ab3e992e392bedd2ccac01da666c?s=96&d=mm&r=g","caption":"rob"}}]}},"_links":{"self":[{"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/posts\/239","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/comments?post=239"}],"version-history":[{"count":0,"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/posts\/239\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/media?parent=239"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/categories?post=239"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/tags?post=239"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}