If you're using the resource owner password flow, you don't need an application, client id or secret. But you need to ask the user for credentials (username and password). If you're asking the user for credentials I would recommend using the authorization code flow instread, i.e. just an application with a client id.
How are you hosting the Next.js appplication, in the same application/hostname as the CMS? If so, then I would recommend just using cookie authentication instead. Much easier and more convenient to implement. If you're hosting the Next.js app on another hostname, you can also put it behind a reverse proxy, using Yarp, in the CMS and then use cookie auth as well.
Yes, I am using a reverse proxy and I want to use the CmsAspNetIdentity with the ContentManagementApi.
I have tried this in order to do so:
services.AddContentManagementApi(IdentityConstants.ApplicationScheme);
My CmsAspNetIdentity is set as follows:
services.Configure<DataAccessOptions>(options => options.ConnectionStrings.Add(new ConnectionStringOptions
{
Name = "EcfSqlConnection",
ConnectionString = _configuration.GetConnectionString("EcfSqlConnection")
}));
services.AddCmsAspNetIdentity<SiteUser>(o =>
{
if (string.IsNullOrEmpty(o.ConnectionStringOptions?.ConnectionString))
{
o.ConnectionStringOptions = new ConnectionStringOptions
{
Name = "EcfSqlConnection",
ConnectionString = _configuration.GetConnectionString("EcfSqlConnection")
};
}
});
Testing it on Postman using the cookies that I have on the browser from cms admin page (which includes .AspNetCore.Identity.Application and antiforgery) prompts me with the cms login page as a response from the api call.
Is there a way to make the CmsAspNetIdentity schema work with the ContentManagementAPI?
I don't think you need to specify a schema at all. Have you tried just services.AddContentManagementApi();
? And what error did you get, 401 or 403? The latter means you don't have sufficient permissions.
I did try not adding any schema but I still get the same result. 200 status code with the response being the html of the optimizely cms login page as the following:
<!DOCTYPE html>
<html lang="en">
<head id="Head1" runat="server">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<link rel="shortcut icon" href="/Util/images/favicon.ico" type="image/x-icon" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex,nofollow" />
<link type="text/css" rel="stylesheet" href="/Util/styles/login.css" />
</head>
<body class="epi-workspace">
<div class="top-bar">
<img src="/Util/images/brand-logo.svg" alt="logo" class="logo" />
<span class="product-name">Optimizely</span>
</div>
<form action="/Util/Login" method="post">
<div id="LoginControl" class="js-login-wrapper login-wrapper">
<div class="modal">
<ol class="clearfix">
<li class="login-header-container"><span class="login-header">Log in</span></li>
<li>
<div class="text--error">
</div>
</li>
<li>
<label for="UserName">Name</label>
<input name="UserName" type="text" id="UserName" autofocus />
</li>
<li>
<label for="Password">Password</label>
<input name="Password" type="password" id="Password" />
</li>
<li>
<input type="submit" name="Submit" value="Log in" id="Submit" class="epi-button-child-item" />
</li>
<li>
<p class="text--small">
<a href="#" onclick="toggleCookieText(); return false;">When you log in, cookies will be
used.</a>
</p>
<div id="cookieInfoPanel" class="cookie-information">
<p class="text--small">
A cookie containing login information will be sent to your web browser. If you do not
want to receive cookies, you will be unable to log into the website.
</p>
</div>
</li>
<li>
<input id="RetunrUrl" name="ReturnUrl" type="hidden" value="/api/episerver/v3.0/contentmanagement/3270d2cd-415e-4412-ba45-133d2650916b" />
</li>
</ol>
</div>
</div>
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8Bd-3W3evRlFsqdDs3kz6bx7vYwkR45f8C3M1YNMSPpSGRtAlf-30xK4Dh1-RUgk0OC6RmvkGSSs0LBpHPnn6oI5yChrwbcaD8Zk6KAYfgMIOCbyTqkvw1oV0JkQCKeCInyhkkATtaC772fu8h3KmfUGLpSt_UfEW_fJGPZkcvlabn9vvJuATh1TpU3fVYGDNg" /></form>
<script>
var classes = [' img1', ' img2', ' img3'];
document.getElementById("LoginControl").className += classes[Math.floor(Math.random() * classes.length)]
function toggleCookieText() {
document.getElementById("cookieInfoPanel").classList.toggle("is-visible");
return false;
}
document.getElementById("Submit").onclick = function () {
if (window.location.hash && window.location.hash.length > 1) {
var encodedHash = encodeURIComponent(window.location.hash.substr(1));
var expiresDate = new Date();
expiresDate.setTime(expiresDate.getTime() + (5 * 60 * 1000));
document.cookie = 'epihash=' + encodedHash + '; path=/; expires=' + expiresDate.toGMTString();
}
}
</script>
</body>
</html>
In a Headless environement (Optimizely Backend and NextJS), we are currently implementing content updating and viewing it on the edit page before publishing it using the Content Management API.
We are using OpenIDDict to authenticate into the API.
Using Postman we are able to call the Content Management API using the Password flow as follows:
REQUEST:
/api/episerver/connect/token
x-www-form-urlencoded body:
grant_type:password
client_id:postman-client
client_secret:postman
username:admin@example.com
password:Episerver123!
Now in our NextJS environment we are trying to call the Content Management API when the user is on the cms edit pages. However, we can't find a good way to authenticate into the API without bringing up one more login screen (Besides the Optimizely CMS Admin login) to be able to authenticate, or hardcode the credentials into our NextJS application.
Is there an optimal way to authenticate into the Content Management API in order to view the saved content before publishing it?