I have code to create/update jobs on Jenkins without credentials enabled.
const string FORMAT = "http://{0}:{1}/createItem?name={2}";
var path =
string.Format(
FORMAT,
this.config.JenkinsServer,
this.config.JenkinsPort,
buildName);
this.http.UploadString(
path,
definition,
new Header(HttpRequestHeader.ContentType, "text/xml"));
Now, I want to move one step forward by enable credentials and specify username/password when creating a new job. I found an article about Authenticating scripted clients on Jenkins but there is no code example in C# and couldn't figure it out how to do it.
How to create/update jobs on Jenkins with credentials enabled?
[UPDATE]
Specify username and password on the url like in this link also doesn't work.
You can authenticate to Jenkins using a user based AUTHTOKEN.
Get the token by going to you user configuration page.
http://{JENKINS.HOST}/user/{YOUR.USERNAME}/configure
Then click the 'Show API Token' button, and it will display a GUID as an AuthToken, which you can then use with something like the following.
string password = "5agbe1d6f774634169e9ba4625559bc83f"; // AKA the Jenkins AuthToken
string userName = "YOUR.USERNAME"; // AKA your Jenkins userID
var webClient = new System.Net.WebClient();
// Create a basic auth token from a username and password seperated by a colon then base 64encoded
string basicAuthToken = Convert.ToBase64String(Encoding.Default.GetBytes(userName + ":" + password));
webClient.Headers["Authorization"] = "Basic " + basicAuthToken;
return client.UploadString(path, definition, headers);
Related
I am creating users via the C# Management Api. Using passwordless, this automatically causes an email to go out. That part works great!
When I click the link in the email, it pops up my Auth0 instance, and I'm getting the "Oops! Something went wrong" message... In the querystring, I can clearly see that redirect_uri is empty, and I assume that must be the problem. Hitting F12, this seems to be confirmed - it's failing on something called VerifyRedirect.
So how do I set this redirect_uri? I am using the C# SDK, and I don't see a way to set it in UserCreateRequest. I also don't see it in the dashboard. What am I missing?
Here's my test code:
var request = new UserCreateRequest()
{
Connection = "email",
Email = email,
EmailVerified = false,
VerifyEmail = true,
FirstName = first,
LastName = last,
FullName = first + " " + last,
AppMetadata = new
{
roles = "Admin"
}
};
// Just dodging async while I test - remember, this part works.
var result = client.Users
.CreateAsync(request)
.GetAwaiter()
.GetResult();
When you create an user via the management API, the redirect URI is set to the first available callback URLs in your client. You can check the client ID in the query string to determine the client and add the redirect URI in its settings.
Note that you don't have to actually create a user like this to start the passwordless flow on an email. If you use the Passwordless​Email​Request object, you can set the client ID and redirect URI (inside AuthenticationParameters) explicitly, so they will not be implicitly deduced.
My web service is currently doing basic username/password authentication in order to subscribe the exchange user for receiving the events (like new mail event etc) like below:
var service = new ExchangeService(exchangeVersion)
{
KeepAlive = true,
Url = new Uri("some autodiscovery url"),
Credentials = new NetworkCredential(username, password)
};
var subscription = service.SubscribeToPushNotifications(
new[] { inboxFolderFoldeID },
new Uri("some post back url"),
15,
null,
EventType.NewMail,
EventType.Created,
EventType.Deleted,
EventType.Modified,
EventType.Moved,
EventType.Copied);
Now, I am supposed to replace the authentication mechanism to use OAuth protocol. I saw some examples but all of them seem to be talking about authenticating the client (https://msdn.microsoft.com/en-us/library/office/dn903761%28v=exchg.150%29.aspx?f=255&MSPPError=-2147217396) but nowhere I was able to find an example of how to authenticate an exchange user with OAuth protocol. Any code sample will help a lot. Thanks.
It's not clear what you mean with 'web service' and how you currently get the username and password. If that is some kind of website where the user needs to login or pass credentials, then you'll have to start an OAuth2 grant from the browser as in redirecting the clients browser to the authorize endpoint to start implicit grant or code grant. The user will be presented a login screen on the OAuth2 server (and not in your application), once the user logs in a code or access token (depending on the grant) will be returned to your application which you can use in the ExchangeService constructor.
If that 'web' service is some service that runs on the users computer you can use one of the methods described below.
Get AccessToken using AuthenticationContext
The example seems to be based on an older version of the AuthenticationContext class.
The other version seems to be newer, also the AcquireToken is now renamed to AcquireTokenAsync / AcquireTokenSilentAsync.
No matter which version you're using, you will not be able to pass username and password like you're doing in your current code. However, you can let the AcquireToken[Async] method prompt for credentials to the user. Which, let's be honest, is more secure then letting your application deal with those user secrets directly. Before you know, you'll be storing plain text passwords in a database (hope you aren't already).
In both versions, those methods have a lot of overloads all with different parameters and slightly different functionality. For your use-case I think these are interesting:
New: AcquireTokenAsync(string, string, Uri, IPlatformParameters) where IPlatformParameters could be new PlatformParameters(PromptBehavior.Auto)
Old: AcquireToken(string, string, Uri, PromptBehavior where prompt behavior could be PromptBehavior.Auto
Prompt behavior auto, in both vesions, means: the user will be asked for credentials when they're not already cached. Both AuthenticationContext constructors allow you to pass a token-cache which is something you can implement yourself f.e. to cache tokens in memory, file or database (see this article for an example file cache implementation).
Get AccessToken manually
If you really want to pass in the user credentials from code without prompting the user, there is always a way around. In this case you'll have to implement the Resource Owner Password Credentials grant as outlined in OAuth2 specificatioin / RFC6749.
Coincidence or not, I have an open-source library called oauth2-client-handler that implements this for use with HttpClient, but anyway, if you want to go this route you can dig into that code, especially starting from this method.
Use Access Token
Once you have an access token, you can proceed with the samples on this MSDN page, f.e.:
var service = new ExchangeService(exchangeVersion)
{
KeepAlive = true,
Url = new Uri("some autodiscovery url"),
Credentials = new OAuthCredentials(authenticationResult.AccessToken))
};
In case someone is still struggling to get it to work. We need to upload a certificate manifest on azure portal for the application and then use the same certificate to authenticate the client for getting the access token. For more details please see: https://blogs.msdn.microsoft.com/exchangedev/2015/01/21/building-daemon-or-service-apps-with-office-365-mail-calendar-and-contacts-apis-oauth2-client-credential-flow/
Using the example code in this Microsoft Document as the starting point and these libraries:
Microsoft Identity Client 4.27
EWS Managed API v2.2
I am able to successfully authenticate and connect with Exchange on Office 365.
public void Connect_OAuth()
{
var cca = ConfidentialClientApplicationBuilder
.Create ( ConfigurationManager.AppSettings[ "appId" ] )
.WithClientSecret( ConfigurationManager.AppSettings[ "clientSecret" ] )
.WithTenantId ( ConfigurationManager.AppSettings[ "tenantId" ] )
.Build();
var ewsScopes = new string[] { "https://outlook.office365.com/.default" };
AuthenticationResult authResult = null;
try
{
authResult = cca.AcquireTokenForClient( ewsScopes ).ExecuteAsync().Result;
}
catch( Exception ex )
{
Console.WriteLine( "Error: " + ex );
}
try
{
var ewsClient = new ExchangeService();
ewsClient.Url = new Uri( "https://outlook.office365.com/EWS/Exchange.asmx" );
ewsClient.Credentials = new OAuthCredentials( authResult.AccessToken );
ewsClient.ImpersonatedUserId = new ImpersonatedUserId( ConnectingIdType.SmtpAddress, "ccc#pppsystems.co.uk" );
ewsClient.HttpHeaders.Add( "X-AnchorMailbox", "ccc#pppsystems.co.uk" );
var folders = ewsClient.FindFolders( WellKnownFolderName.MsgFolderRoot, new FolderView( 10 ) );
foreach( var folder in folders )
{
Console.WriteLine( "" + folder.DisplayName );
}
}
catch( Exception ex )
{
Console.WriteLine( "Error: " + ex );
}
}
The Microsoft example code did not work - the async call to AcquireTokenForClient never returned.
By calling AcquireTokenForClient in a separate try catch block catching a general Exception, removing the await and using .Result, this now works - nothing else was changed.
I realise that this is not best practice but, both with and without the debugger, the async call in the original code never returned.
In the Azure set-up:
A client secret text string was used - a x509 certificate was not necessary
The configuration was 'app-only authentication'
Hope this helps someone avoid hours of frustration.
This is in context of multi-tenanted web solution, which intends to provide its users access to Office 365 calendar records via making REST API calls. User will be required to authenticate with Azure AD in order to have access.
This is what I'm doing.
0 ============= Windows Azure test account setup and Application is registered
I have set up an account on Windows Azure (presumably coupled with Office 365), using test e-mail that was initially created on Gmail.
I have registered my application within Windows Azure Active Directory, and provided this application with all access permissions possible. Basically added all possible resources and then ticked all the boxes for each. Client Secret key has also been issued.
1 ============= Redirecting Browser to Microsoft Login page
In my jabascript side of code, the following URL is constructed:
var url = 'https://login.microsoftonline.com/'
+ {tenant}
+ '/oauth2/authorize'
+ '?response_type=code'
+ '&client_id=' + {application_id}
+ '&redirect_uri=' + encodeURI({response_page_url})
+ '&state=' + {guid_1}
+ '&nonce=' + {guid_2}
;
Then redirection happens:
window.location.replace(url);
2 ============= Microsoft Login happens
Browser opens the Microsoft Login page, which asks for user e-mail and password. Once user e-mail is typed in and focus is changed to password, the page suddenly flips to something else and asks for e-mail again, and the for the password. Great Usability Microsoft!
3 ============= Back to Login Completion page
Once Microsoft Login procedure is over, browser lands to my http://localhost:5000/something page with some arguments in the query string.
I extract "state", "session_state", and "code" from the query string and pass it to server to do the next step.
4 ============= Trying to retrieve "id_token" for the "code"
On the server side, in C# code to be specific, I am trying to acquire "access_code" and "id_token" from Microsoft AD by the following request:
var url = "https://login.windows.net/common/oauth2/token";
var post = "grant_type=authorization_code"
+ "&code=" + {code_received_at_previous_step}
+ "&redirect_uri=" + HttpUtility.UrlEncode({same_redirect_url_as_before})
+ "&client_id=" + {application_id}
+ "&client_secret=" + {secret_key_issued_by_azure_ad}
+ "&resource=" + HttpUtility.UrlEncode("https://outlook.office365.com")
;
byte[] postData = new UTF8Encoding().GetBytes(post);
var request = WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postData.Length;
using (var os = request.GetRequestStream())
{
os.Write(postData, 0, postData.Length);
}
WebResponse response;
bool isError = false;
try
{
response = request.GetResponse();
}
catch (WebException up)
{
isError = true;
response = up.Response;
}
string responseText = null;
using (response)
{
using (var dataStream = response.GetResponseStream())
using (var reader = new StreamReader(dataStream))
{
responseText = reader.ReadToEnd();
}
}
var json = Json.Parse(responseText);
if (isError)
{
throw new System.Exception(string.Format("{0}:{1}", json["error"], json["error_description"]));
}
At the last step an Exception is thrown with the following details:
An exception of type 'System.Exception' occurred in IdentityManagement.dll but was not handled in user code
Additional information: invalid_grant:AADSTS65001: The user or administrator has not consented to use the application with ID '{guid}'. Send an interactive authorization request for this user and resource.
Trace ID: 6fc18926-36bd-4731-a128-54fcb320718a
Correlation ID: 75a7617e-f03f-4d57-bdd2-f655dd615a2a
Timestamp: 2016-12-05 01:15:06Z
JSON data received in response in my case is the following:
{{"error":"invalid_grant","error_description":"AADSTS65001: The user or administrator has not consented to use the application with ID '{guid}'. Send an interactive authorization request for this user and resource.\u000D\u000ATrace ID: 6fc18926-36bd-4731-a128-54fcb320718a\u000D\u000ACorrelation ID: 75a7617e-f03f-4d57-bdd2-f655dd615a2a\u000D\u000ATimestamp: 2016-12-05 01:15:06Z","error_codes":[65001],"timestamp":"2016-12-05 01:15:06Z","trace_id":"6fc18926-36bd-4731-a128-54fcb320718a","correlation_id":"75a7617e-f03f-4d57-bdd2-f655dd615a2a"}}
So my questions are:
What is missing from my setup, environment, code or the execution AND how to fix it?
Is there a working example of C#/Javascript code that is successfully getting say calendar events from Office 365 via API requests (not functional calls to some libraries)?
Is there anyone who cal get in touch via Skype or something to help me with making my example working?
Great thanks is advance!
Much appreciate your attention.
It may be that you are requesting a scope that requires an administrator to consent, in which case an administrator for the organization must sign in and approve your app. The different scopes and whether they require administrative consent are here: https://graph.microsoft.io/en-us/docs/authorization/permission_scopes
Or possibly you aren't requesting any scopes at all? I don't see it in your URLs.
I wonder if it is possible to get a permanent access token for personal use on Reddit?
It will only be me using the App.
For users, the access token expires after 1 hour.
My using the below information that I have about my client-id and secret, I put up a start attempt of trying to get an access token. (MessageBox show "Error 401")
If a user will get a token, one have to click "Allow" in the browser. Very well described here. https://github.com/reddit/reddit/wiki/OAuth2
This it NOT what I am after. I am after for, personal use, an access token only through code. Is this possible?
String requestUrl = "https://ssl.reddit.com/api/v1/access_token";
RestSharp.RestClient rc = new RestSharp.RestClient();
RestSharp.RestRequest request = new RestSharp.RestRequest(requestUrl, RestSharp.Method.POST);
request.AddHeader("Content-Type", "application/json");
//request.AddHeader("Authorization", ""); //???
request.AddHeader("x-li-format", "json");
request.AddParameter("client_id", "abcdefg");
request.AddParameter("client_secret", "abc123-456");
request.AddParameter("grant_type", "abc123-456");
request.AddParameter("scope", "identity");
request.AddParameter("state", "adhasegw"); //whatever value
request.AddParameter("duration", "permanent");
request.AddParameter("redirect_uri", "http://mywebsite.co");
request.RequestFormat = RestSharp.DataFormat.Json;
RestSharp.RestResponse restResponse = (RestSharp.RestResponse)rc.Execute(request);
RestSharp.ResponseStatus responseStatus = restResponse.ResponseStatus;
MessageBox.Show(restResponse.Content.ToString() + "," + responseStatus.ToString());
As of right now, you cannot retrieve a permanent access token. You have 2 options that come close.
The first is to request a "refresh" token when using the standard OAuth flow. That's what you're doing by sending "duration" as "permanent" in your code. The refresh token can be used to automatically retrieve new 1 hour access tokens without user intervention; the only manual steps are on the initial retrieval of the refresh token.
The second alternative, which applies only when writing a script for personal use, is to use the password grant type. The steps are described in more detail on reddit's "OAuth Quick Start" wiki page, but I'll summarize here:
Create an OAuth client (under https://www.reddit.com/prefs/apps) with type = "script"
Make a request to https://www.reddit.com/api/v1/access_token with POST parameters grant_type=password&username=<USERNAME>&password=<PASSWORD>. Send your client ID and secret as HTTP basic authentication. <USERNAME> must be registered as a developer of the OAuth 2 client ID you send.
A client_id and client_secret can be generated for a reddit account by going to https://www.reddit.com/prefs/apps and creating an app:
The part I have hidden is my client_id.
Then you can use a client like praw to access reddit e.g. with Python:
import praw
r = praw.Reddit(client_id='insert id here',
client_secret='insert secret here',
user_agent='insert user agent')
page = r.subreddit('aww')
top_posts = page.hot(limit=None)
for post in top_posts:
print(post.title, post.ups)
You could use your current browser's user agent, which can be easily found by google searching "what is my user agent" (among other ways).
There are lots of sample applications in MVC but the current project I'm working on requires that I use web forms.
I can authorize the application using the javascript method but I want to use server side. Below is what I started with on the page.load
dynamic parameters = new ExpandoObject();
parameters.client_id = AppId;
parameters.client_secret = appSecret;
parameters.response_type = "code";
//parameters.state = state;
parameters.redirect_uri = "http://fb.local/page.aspx";
// The requested response: an access token (token), an authorization code (code), or both (code token).
parameters.response_type = "token";
// list of additional display modes can be found at http://developers.facebook.com/docs/reference/dialogs/#display
//parameters.display = "popup";
// add the 'scope' parameter only if we have extendedPermissions.
if (!string.IsNullOrWhiteSpace(ExtendedPermissions))
parameters.scope = ExtendedPermissions;
// generate the login url
var fb = new FacebookClient();
var loginUrl = fb.GetLoginUrl(parameters);
Response.Redirect(loginUrl.AbsoluteUri, true);
I can authorize but I'm not able to get the access token from the URL.
On the next page I can view source and see the access token in the url bar but I'm not sure how to go about getting it into the code. once I have the token, I'm all set.
page.aspx#access_token=AAACrxQhmdpY
I used to this code on my page load and works, its not a very clean code, but you may figure out how to change it for your best use. so the algorithm is that when the page loads you redirect the user to Facebook authentication page using response.redirect to a string that contains three parameters:your app ID(appid), what permissions you are asking your user(scope), where you want Facebook to redirect the user after authorization, and a parameter as state which i guess it should be a random number. so after the user authorized your application he/she will be redirected to your page, with a request URL that contains the same state you prepared Facebook with(and you can use to identify who which request was which if there are many requests i guess) and also a new "code" parameter which you pass on to Facebook to obtain access token, you can use Facebook c# sdk to obtain the access token.in my code there is a line that says "if code is not null, go to alireza" and alireza is a line tag after the response.redirect code, this is because you dont want the process to be repeated all over and over (and of course probably the browser show an error).
int intstate;
string strstate;
string redirecturltofb;
string scope;
string appid;
code = Request.QueryString["code"];
if (!String.IsNullOrWhiteSpace(code))
{
goto alireza;
}
appid = "424047057656831";
scope = "user_about_me,user_activities,user_groups,email,publish_stream,user_birthday";
intstate = 45;
strstate = Convert.ToString(intstate);
redirecturltofb = "https://www.facebook.com/dialog/oauth?client_id=" + appid + "&redirect_uri=http://test5-2.apphb.com/&scope=" + scope + "&state=" + strstate;
Response.Redirect(redirecturltofb);
You have to use Javascript SDK to get access token back to code behind.
Use FB.Init as in http://csharpsdk.org/docs/web/getting-started
and do post back on certain conditions to get the access token.
Thank you,
Dharmendra