Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • mmaty 117 posts 311 karma points
    17 days ago
    mmaty
    0

    Umbraco 15 Backoffice API

    I'm going my first steps with Umbraco 15. What I want to achieve is getting and calling a backoffice api controller like it was possible with UmbracoAuthorizedApiController in the past.

    I learned, that the APIs now have the route /umbraco/management/api/v1/ plus some additional route segments. I can't manage to get a simple controller done. Consider the following code:

    [VersionedApiBackOfficeRoute("laykit/environment")]
    [ApiVersion("1.0")]
    public class EnvironmentController : ManagementApiControllerBase
    {
        [HttpGet]
        public string Get()
        {
            return "Teststring";
        }
    }
    

    What is the right route to call this API from my backoffice extension? Is the above definition false? This would be the client code:

    fetch("/umbraco/management/api/v1/laykit/environment")
        .then(data=>this.data = data);
    

    I tried with and without the get segment, it doesn't work. What I also want to achieve is, that the backoffice login should be sufficient to be authorized to all this api.

    Do you have any insights to share, which makes this working?

  • Yasir Butt 162 posts 372 karma points
    15 days ago
    Yasir Butt
    0

    Hi,

    Here is my simple backoffice controller for my custom section.

        [ApiController]
    [BackOfficeRoute("api/v{version:apiVersion}/[controller]")]
    [Authorize(Policy = AuthorizationPolicies.BackOfficeAccess)]
    [MapToApi("ich")]
    public class BackOfficeControllerBase : ControllerBase
    { }
    

    You need some other configuration to make it work.

    public class IchBackofficeApiOperationSecurityFilter : BackOfficeSecurityRequirementsOperationFilterBase
     {
         protected override string ApiName => "ich";
     }
    

    Your swagger config if you need it

     internal class ConfigureBackofficeSwaggerGenOptions : IConfigureOptions<SwaggerGenOptions>
     {
         public void Configure(SwaggerGenOptions options)
         {
             options.SwaggerDoc(
                 "ich",
                new Microsoft.OpenApi.Models.OpenApiInfo
                {
                    Title = "Ich Backoffice Api",
                    Version = "1.0",
                    Description = "Ich backoffice Api"
                });
             options.OperationFilter<IchBackofficeApiOperationSecurityFilter>();
              var schemaHelper = new SwashbuckleSchemaHelper();
              options.CustomSchemaIds(type => schemaHelper.GetSchemaId(type));
             //options.OperationFilter<TimeBackOfficeSecurityRequirementsOperationFilter>();
         }
     }
    

    And a composer

    public class IchApiComposer : IComposer
     {
         public void Compose(IUmbracoBuilder builder)
         {
             builder.Services.ConfigureOptions<ConfigureBackofficeSwaggerGenOptions>();
         }
     }
    

    Hope it will help you.

    /Yasir

  • mmaty 117 posts 311 karma points
    1 week ago
    mmaty
    0

    @yasir: Thanks for your answer. I tried to implement your approach and the api shows up in /umbraco/swagger. That's good. But if I try it in in the swagger UI, it shows me a 401 status code:

    www-authenticate: Bearer error="invalid_token",error_description="The specified token is invalid.",error_uri="https://documentation.openiddict.com/errors/ID2004" 
    

    In the same browser in another tab I am logged in into the backoffice. What can I do to avoid these 401 errors?

  • mmaty 117 posts 311 karma points
    1 week ago
    mmaty
    100

    If anybody searches for an answer to this question, here is the solution.

    import { OpenAPI } from '@umbraco-cms/backoffice/external/backend-api';
    ...
    @customElement('ff-dashboard')
    export class FFDashboard extends LitElement {
      @property()
      environment = 'Unknown'
    
      async connectedCallback(): Promise<void> {
    
        umbExtensionsRegistry.exclude('Umb.Dashboard.UmbracoNews');
    
        const tokenPromise = (OpenAPI.TOKEN as any as () => Promise<string>);
        const token = await tokenPromise();
    
        let response = await fetch("/umbraco/backoffice/api/environment", {
            method:'GET', 
            headers:{
                'Authorization':'Bearer ' + token
            }
        });
        this.environment = await response.json();
        super.connectedCallback();
      }
    

    I had to get the token of the current logon session. This happens in the two lines beginning with "const tokenPromise = ....".

    After the second line we have the token and can set it in an request header as shown. The controller works like @yasir has shown above (with altered route and ApiName).

  • jcrmerlin 4 posts 74 karma points
    4 days ago
    jcrmerlin
    0

    Wow, it took me an hour searching for an answer and here it is, plain and simple. Thanks a lot!

Please Sign in or register to post replies

Write your reply to:

Draft