[英]Keycloack for native /desktop application in c# REST APIs, not working properly or am I missing something?
I can get the authorization code and access token by a keycloak endpoint ONLY when I already have the browser opened and already did the login, otherwise the code fails to get the authorization code.只有当我已经打开浏览器并已经登录时,我才能通过 keycloak 端点获取授权码和访问令牌,否则代码无法获取授权码。
so considering I implement this logic at the application start ( it's not definitive ) , I have to run it 2 times to get code and then the token.所以考虑到我在应用程序开始时实现了这个逻辑(它不是确定的),我必须运行它 2 次才能获取代码,然后是令牌。
I just use rest APIs because I can not find an understandable keycloak library to use for desktop / native applications.我只使用rest API,因为我找不到可用于桌面/本机应用程序的可理解的keycloak库。
this is my code:这是我的代码:
public static async Task<string> GetTokenAsync()
{
string redirectURI = string.Format("http://{0}:{1}/", "localhost", GetRandomUnusedPort());
string RedirectURIWithoutLastSlash = redirectURI.TrimEnd('/');
string code = await GetCodeForAuthentication(redirectURI, RedirectURIWithoutLastSlash);
UnityWebRequest request = new UnityWebRequest();
request.url = $"https://tokenEndpoint.../protocol/openid-connect/token";
request.method = UnityWebRequest.kHttpVerbPOST;
request.downloadHandler = new DownloadHandlerBuffer();
request.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded");
string postData = "";
Dictionary<string, string> postParameters = new Dictionary<string, string>() /
{
{"grant_type", "authorization_code"},
{"code", code},
{"client_id", "myID"},
{"client_secret", "mySECRET"},
{"redirect_uri", RedirectURIWithoutLastSlash }
};
foreach (string key in postParameters.Keys)
postData += UnityWebRequest.EscapeURL(key) + "=" + UnityWebRequest.EscapeURL(postParameters[key]) + "&";
byte[] data = Encoding.ASCII.GetBytes(postData);
request.uploadHandler = new UploadHandlerRaw(data) ;
request.timeout = 60;
request.SendWebRequest();
while (!request.isDone)
{
Debug.Log(request.downloadProgress);
}
Debug.Log("text by server is: " + request.downloadHandler.text);
TokenClass token = JsonUtility.FromJson<TokenClass>(request.downloadHandler.text);
access_token = token.access_token;
tokenInfo = token;
Debug.Log("access token is: " + access_token);
return access_token;
}
private static async Task<string> GetCodeForAuthentication(string redirectURI, string RedirectURIWithoutLastSlash)
{
string code = null;
HttpListener http = new HttpListener();
http.Prefixes.Add(redirectURI);
http.Start();
string authorizationRequest = $"https://authCode Endpoint.../protocol/openid-connect/auth?client_id=myID&response_type=code&response_mode=query&scope=profile&redirect_uri={RedirectURIWithoutLastSlash}";
// Opens request in the browser.
Process web_Login_Process = new Process();
web_Login_Process.StartInfo.FileName = GetSystemDefaultBrowser();
web_Login_Process.StartInfo.Arguments = authorizationRequest;
web_Login_Process.Start();
try
{
var context = await http.GetContextAsync();
var response = context.Response;
var html = "<html><head><meta http-equiv='refresh' content='10;url=https://localhost'></head><body>Please return to the Digital Twin.</body></html>";
string responseString = string.Format(html);
var buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;
var responseOutput = response.OutputStream;
Task responseTask = responseOutput.WriteAsync(buffer, 0, buffer.Length).ContinueWith((task) =>
{
responseOutput.Close();
http.Stop();
Console.WriteLine("HTTP server stopped.");
});
// Checks for errors.
if (context.Request.QueryString.Get("error") != null)
{
string debug = context.Request.QueryString.Get("error");
}
if (context.Request.QueryString.Get("code") == null
|| context.Request.QueryString.Get("state") == null)
{
var debug = context.Request.QueryString; //no keys, Lenght is equal to 0
var debug3 = context.Request.RawUrl; // favicon.ico is the result
}
// extracts the code
code = context.Request.QueryString.Get("code");
string tryCode = context.Request.QueryString["code"];
Debug.Log("code is: " + code);
}
catch (Exception ex)
{
string g = ex.Message;
}
return code;
}
any help on this would be really appreciated.对此的任何帮助将不胜感激。
There is a C# Sample that you can follow for the desktop flow and borrow some ideas from.有一个C# 示例,您可以遵循桌面流程并从中借鉴一些想法。 Note that the OAuth flow for console apps is the same as for desktop apps.
请注意,控制台应用程序的 OAuth 流程与桌面应用程序相同。
You should be using PKCE for the desktop app security and the above library will implement this for you您应该将 PKCE 用于桌面应用程序安全性,上面的库将为您实现这一点
For something to compare against with the correct OAuth behaviour, see these resources of mine:要与正确的 OAuth 行为进行比较,请参阅我的这些资源:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.