I'm currently writing a C# metro app for the Windows 8 consumer preview which fetches some data from my REST-based web services. I want the app to authenticate against the services using the Windows Live account of the current user. Therefore, I added the Windows Live SDK to my solution and pasted the following snippet from the documentation into my login view:
LiveAuthClient liveClient = new LiveAuthClient();
LiveLoginResult loginResult = await liveClient.Login(new string[] { "wl.signin" });
After the login call has succeeded, I want to pass the encrypted AuthenticationToken of the LiveConnectSession via SSL to my webservice which should decrypt the token and read the information it is interested in (that's what the documentation suggests for such a SSO scenario). But sadly, the AuthenticationToken property of the session is always null. Am I missing something here?
I ran into the same problem and realised I had two issues with my configuration:
I didn't have a "Redirect domain" defined in the API settings of https://manage.dev.live.com
I wasn't using the overloaded LiveAuthClient constructor
For example in the API settings you specify:
Redirect domain: http://localhost/myapp
You then use the constructor overload of the LiveAuthClient:
var authClient = new LiveAuthClient("http://localhost/myapp");
var loginResult = await authClient.LoginAsync("wl-signin");
//this should no longer be null
var authToken = loginResult.Session.AuthenticationToken;
The redirect URI doesn't need to point to a working endpoint from what I can tell, as long as the two values match you should be in business.
Have you registered your app on the Live Connect app management site for Metro style apps? You need to register it here for it to work with Live Services. It will give you following instructions after you have given the app package a name and publisher.
Related
there
I want to use JIRA API to access data from my company's JIRA instance. The steps of login process on internet browser are:
Type https://mycompanyname.atlassian.net
Direct to login page.
Type my company email address
It re-directly to Microsoft authentication page, click "Continue".
Type password of my Azure AD domain account.
Select a method to verify my identify (I select way of verifying code sent to my bind mobile)
Bingo!
My questions are:
1.How can I finish above steps by C# code?
2.Does my application need the mobile text code verification for every instance?
FYI:
I want to put my application on Azure function as a timer trigger to run some data from JIRA. However, I get stuck at first step-authentication.
I do not know if you have already solved your issue. But from an azure function there is a few steps you will need to take.
In Azure use Managed Identity, you will need this for function to get some details you will save into Keyvault
Have a Keyvault ready cause you gonna need it to get some secrets out of it
Create your Function app and install Atlassian.SDK - can see documentation here
In the dependency injection of your function call
var config = new ConfigurationBuilder()
.AddAzureKeyVault(secretClient, new KeyVaultSecretManager())
.AddEnvironmentVariables()
.Build();
container.Register(p => Options.Create(config.Get<ConfigDetailsModel>()))
.SingleInstance();
In your Jira service use the following to signin
public JiraService(IOptions<ConfigDetailsModel> config)
{
_config = config.Value;
}
var jira = Jira.CreateRestClient(_config.JiraUri, _config.JiraUserName, _config.JiraApiKey);
var result = await jira.Projects.GetProjectsAsync();
Go to https://id.atlassian.com/manage-profile/security/api-tokens and create an API key for your password as plaintext passwords are not supported anymore by Jira.
Save your username, password and url into keyvault, make password expire at some point.
This should work. Unfortunately the OAUTH way, more secure than the basic way is not really geared towards system-to-system way, well not that I could find, as it requires a user input to allow verification code. If you do not mind moving the flow out of function and into a user flow with OAuth then best article I found is here, but you need to copy additional things from his github to get it to work. I got this flow working in Blazor, and tried to get it to work in my Servicebus triggered function.
The only way I could get the Jira stuff to work in function for service-to-service was to use basic Auth either via the Atlassian.SDK or Httpclient
Note SDK makes life somewhat easier than writing own http client stuff
var client = new HttpClient
{
BaseAddress = new Uri(_config.JiraUri)
};
client.DefaultRequestHeaders.Accept.Clear();
var authenticationString = $"{_config.JiraUSerName}:{_config.JiraApiKey}";
var base64EncodedAuthenticationString = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(authenticationString));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64EncodedAuthenticationString);
var project = await client.GetAsync($"rest/agile/1.0/epic/{projectId}");
var content = await project .Content.ReadAsStringAsync();
UPDATE
When you create an API key in Jira for use in code, know that the API key in JIRA is tied to the person who created it.
It should be an Admin account
Create a global break glass account to manage this, you do not want an apikey tied to a user that might leave in a few months
This break glass account should belong to your DevOps team and no one else who can exploit this api key
I have a .NET 4.6.2 Windows client application which needs to get an authentication token from our on-premise ADFS server and use it to call an ASP.NET Core REST API. It's client name, id (GUID) and re-direct URI have been registered with ADFS. I am using the latest ADAL (v3.13) library to facilitate the authentication. I am attempting to get a token as demonstrated in the ADAL sample code like this:
AuthenticationContext authenticationContext = new AuthenticationContext("https://<adfs-sts-server>/<rest-api-host>", false);
var result = authenticationContext.AcquireTokenAsync(<rest-api-resource-uri>, clientId, redirectUri, new PlatformParameters(PromptBehavior.Auto));
The AcquireTokenAsync call returns an error, saying: The browser based authentication dialog failed to complete. Reason: The server has not found anything matching the requested URI (Uniform Resource Identifier).
Can anyone tell me:
Is the "requested URI" refered to in the error the https://<adfs-sts-server>/<rest-api-host> or <rest-api-resource-uri>?
Do I need to register <rest-api-host> or <rest-api-resource-uri> with ADFS in some way, and if so how?
Any other information I need to get this to work?
Thanks!
Peter
Using Active Directory Federation Services (ADFS) to provide authentication for on-premise endpoints from a Windows Client
Configuring ADFS
There are 2 parts to configuring ADFS.
Register the client application with ADFS
ADFS needs to be able to identify the application requesting user authentication, whether it be a service, WPF application, Web client or Office Add-in. I have gone generic and added the following client, which we can use for most of our C# requests; we may need to register a new client with different callback for Web clients.
Use one of the many tools out there to generate a GUID for the client ID.
* CLIENT_ID and APP_NAME should be unique.
* For a web client the redirect URI is where the auth service will redirect your call after authenticating the user. It should be an endpoint where you can process the token and continue with your client application. The redirect URI is not really used with rich clients/services/add-ins.
CLIENT_ID = 26E54EC9-7988-4DAE-A527-483A8A78B1C6
APP_NAME = Investplus
DESCRIPTION = Invest+ rich client suite
REDIRECT_URI = https://server/redirect-adfs.html
Instructions for Client registration
(may be possible in a wizard, but this is what I found on the web and it worked fo us)
Log on to the AD FS server as administrator and open a Windows PowerShell command window.
Enter the following command. In Windows PowerShell
Add-AdfsClient -ClientId <CLIENT_ID> -Name <APP_NAME> -RedirectUri <REDIRECT_URI>
Register the resource to be accessed ('Relying Party' in ADFS speak)
I found this link useful, it takes you through the steps of the wizard for setting up a relying party.
Instructions for Relying Party registration
The administrator on the server team will need to use the ADFS Add Relying Party Trust Wizard, and under the "Select Data Source" step select Enter data about the relying party manually.
Values you need to supply for this wizard:
DISPLAY_NAME = "MyInvestApi" (Unique display name for this Relying party)
PROFILE = "AD FS Profile"
ENABLE_SUPPORT_FOR_WS-FEDERATION_PASSIVE_PROTOCOL = true
URL = "https://server/api" (Unique URL for this RP)
ADD_ONE_OR_MORE_IDENTIFIERS = eg. "urn:myInvestApi" and "https://server/api"
ACCEPT_REMAINING_DEFAULTS
when given the opportunity, Add Claim Rules:
SEND_LDAP_ATTRIBUTES_AS_CLAIMS = true
ATTRIBUTE_STORE = Active Directory
SELECT_USEFUL_ATTRIBUTES = User-Principal-Name; Email; Display-Name
Configuring/Coding the Client application
Microsoft provides Active Directory Authentication Libraries (ADAL) for a range of platforms and languages from C# to Javascript, and from iOS to Cordova to Node.
The API exposed has changed significantly in each major version: I am using the latest C# library, currently 3.13.5.
The library makes the coding very simple, just a few lines; where I had problems was:
I couldn't find an explanation of what URL to use for the ADFS
Secure Token Service (STS)
I couldn't find documentation of the whole process as I am doing here (most documentation focussed on Azure FS), I struggled to work out
how the values provided to ADFS for Client and Relying party mapped
to the values used in the code.
What is the ADFS endpoint/URL to use in code?
Microsoft's best practice is to name your ADFS/STS server URL https://sts.domain.com (some people use https://adfs.domain.com, ask your server admins). However, if you try to hit this from a browser you'll get a 404 - Not found and trying to retrieve a token in the code, the ADAL library reports:
The browser based authentication dialog failed to complete. Reason: The server has not found anything matching the requested URI (Uniform Resource Identifier).
This is how I found the endpoint to use:
ADFS pubishes federation metadata at 'https://sts.domain.com/federationmetadata/2007-06/federationmetadata.xml'
Extract this file and open in a text editor.
When configuring the Relying Party, we specified "Enable Support for WS-Federation Passive Protocol" when specifying our resource endpoint, so search the XML for PassiveRequestorEndpoint.
Use the <Address> from this node - in my case https://sts.domain.com/adfs/ls/. I don't know if this will always be the value, or if it is specified when ADFS is setup and therefore potentially different per site.
What other values to use in the code?
We want our client app to retrieve a JSON Web Token (JWT) from ADFS which we can pass to our protected resource for authentication/authorization purposes.
At its most simple, the access token can be retrieved in 3 lines of code + configuration, and this will show how to translate what we have configured in ADFS to the values required by ADAL:
var stsEndpoint = "https://sts.domain.com/adfs/ls/";
var relyingPartyIdentifier = "urn:myInvestApi"; // Tenant in Azure AD speak, but this is an on-premise service
var authority = stsEndpoint + relyingPartyIdentifier;
var restResourceUrl = "https://server/api";
var redirectUri = "https://server/redirect-adfs.html";
const string CLIENT_ID = "26E54EC9-7988-4DAE-A527-483A8A78B1C6";
AuthenticationContext authenticationContext = new AuthenticationContext(authority, false);
var asyncRequest = authenticationContext.AcquireTokenAsync(restResourceUrl, CLIENT_ID, redirectUri, new PlatformParameters(PromptBehavior.Auto));
var accessToken = asyncRequest.Result.AccessToken;
Useful references
ASP.NET Core Token Authentication Guide
ADAL - Native App to REST service - Authentication with ACS via Browser Dialog
Create a line-of-business Azure app with AD FS authentication
OAuth 2 Simplified
To issue the token for the web API, we need to make the ADFS to aware it by creating a relying party trust for the web API. And when we add a replying party we need to specify the identifiers for the replying party like figure below(Windows Server 2012 R2):
Then we can use this identifiers as the resource URI to acquire the token for this replying party. Please ensure that the resource URI is correct as you config like figure above.
And here is an article about developing with ADFS using OAuth:
Developing Modern Applications using OAuth and Active Directory Federation Services
Depending on the version of asdf, you may be able to use 'discovery' to obtain the endpoints to use.
Have a look at this post for more details: http://www.cloudidentity.com/blog/2015/08/21/openid-connect-web-sign-on-with-adfs-in-windows-server-2016-tp3/
I have a client url in which the open id authentication is implemented .How I can implement Open ID connect simply in UWP Win 10. Can I use web authentication broker for that? If yes how to do it using WebAuthenticationBroker? please provide example
Yes, WebAuthenticationBroker is designed to be used with protocols like OpenID and OAuth.
Basically, in UWP you just need to call authentication method and pass request and callback URIs:
var webAuthenticationResult =
await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None,
requestUri,
callbackUri);
if (webAuthenticationResult.ResponseStatus == WebAuthenticationStatus.Success) {
//String for service response
var data = webAuthenticationResult.ResponseData;
...
} else {
...
}
System will show an overlay UI on top of your app asking user to provide his or her credentials to corresponding website. If credentials are right website will return callbackUri and access token. WebAuthenticationBroker will check callbackUri with the one you provided and if everything was correct you will get your token as a result.
I would also recommend to look at the following repositories on GitHub in case you need custom implementation with WebView:
IdentityModel.OidcClient - implementation of portable library of OpenID Connect
UwpOidcClient - sample implementation of OpenID Connect Client for UWP
My WinForms app needs to access one of the Google API's (Calendar). For this, the app needs to have authorization, and Google has provided OAuth 2 for this purpose. I've read everything on their docs site here.
From another documentation page on Google I learned how to get the authorization key via a browser request. This takes place in a Console C# application. What it does is:
var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description, CLIENT_ID, CLIENT_SECRET);
var auth = new OAuth2Authenticator<NativeApplicationClient>(provider, GetAuthorization);
var service = new CalendarService(auth);
string id = <calendar id>;
Calendar calendar = service.Calendars.Get(id).Fetch();
At the last line, a browser window is opened with a Google page asking me to allow the app access to my Google account. In the console application, a ReadLine() is waiting for input. This comes from the GetAuthorization method:
private static IAuthorizationState GetAuthorization(NativeApplicationClient arg)
{
// Get the auth URL:
IAuthorizationState state = new AuthorizationState(new[] { CalendarService.Scopes.Calendar.GetStringValue() });
state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl);
Uri authUri = arg.RequestUserAuthorization(state);
// Request authorization from the user (by opening a browser window):
Process.Start(authUri.ToString());
Console.Write(" Authorization Code: ");
string authCode = Console.ReadLine();
Console.WriteLine();
// Retrieve the access token by using the authorization code:
return arg.ProcessUserAuthorization(authCode, state);
}
So I grant my app access to my Gmail account, and I get a code in return. This code I paste back into the console window, and the rest of the app does its work as it should (in my case, making a new Calendar event).
But my problem is the fact that I want this functionality in a WinForms app, not a Console app. I have not been able to find anything on Google's pages regarding this.
What I have so far:
User clicks a button, the browser is opened and the user grants access and retrieves the code.
User pastes this code into the app.
Another button is clicked, and this is where I would like to use the user-entered code for the authorization process. This is a string, and I don't know how to combine this with all the authentication methods written in the top of this post.
I have a feeling it could be possible with the use of Google's REST client instead of the native .NET libraries, but I sincerely want to use the .NET libraries instead of REST.
Take a look at the AuthorizationMgr class and in particular at RequestNativeAuthorization method. It uses a LoopbackServerAuthorizationFlow class, which created a tcp listener for you and get the code from the incoming request.
You should also take a look at one of the samples that uses that mechanism (e.g. CreateTask sample)
I'm trying to use the Facebook SDK 5.2.1 to ultimately create a test user, however even what I believe is the simple example of getting the list of test accounts isn't working for me. I get the OAuthException "An access token is required to request this resource."
Here's my code (replace APP ID and APP SECRET with my own):
FacebookOAuthClient oauth = new FacebookOAuthClient { AppId = "APP ID", AppSecret = "APP SECRET" };
dynamic tokenRes = oauth.GetApplicationAccessToken();
fbClient = new FacebookClient(tokenRes.access_token);
dynamic response = fbClient.Get("APPID/accounts/test-users");
However, I get the exception on the fbClient.Get line.
Any idea as to what's wrong?
Thanks,
Chad
After hours of trying various things and reading various web pages/blogs, I found the reason it wasn't working. In my app settings, I had my app type set to a Native/Desktop App. Changing this to Web, allows the above scenario to work. I'm not yet quite sure of what other differences exist between web vs native facebook apps. My app is certainly only being used via a desktop application and I can't understand why I need to set this to Web just to allow me to create test users.
This code works in my app:
var app = new FacebookClient(FacebookApplication.Current.AppId,
FacebookApplication.Current.AppSecret);
dynamic result = app.Post(string.Format("{0}/accounts/test-users",
FacebookApplication.Current.AppId),
new { installed = true, permissions = "user_about_me" });
The reason why you are receiving the exception OAuthException is because you have not yet got the permission of the user.
To do a Graph API call on the current user, you need to get the user to accept the permissions that you require FIRST and then do the Graph API call.
You need to get the user to a browser some how in your application, as there is not an authentication flow which doesn't require a browser window.
Check out this URL to view the authentication flows:
http://developers.facebook.com/docs/authentication/