New help modifying a method

I’m trying to modify this method based off the instructions below but I’m having trouble with a lot of errors in my existing code so far.

If isApproved is true:
a. Assign the response “code” parameter (see above) to a local var, say code.
b. Generate a random 10-character pin value via Convert.ToBase64String(new System.Security.Cryptography.RNGCryptoServiceProvider().GetBytes(buffer)), and assign to a local var, say pin.
c. Create a DateTime (using process described below) for the ExpirationDate
d. Instantiate a AuthorizationPin with { AccessCode = code, Pin = pin, ExpirationDate = expirationDate }. Leave Id as 0. NHibernate will know to allow the database to generate the Id (assuming that the REST API mapping file is configured correctly. See other mapping files in REST API.)
e. Call authPinRepo.Insert(authPin) to save the AuthorizationPin
Instantiate a PinModel with { IsApproved = isApproved, Pin = pin }
return View(“Pin”, model);

This is the code I have so far:

             public ActionResult ProcessAuthorization(bool isApproved)
	{
		Resource resource;
		User user;
		Client client;
		HashSet<string> requestedScopes;
		object code;

		var request = _securityService.ParseAuthorizationRequest(out resource, out user, out client, out requestedScopes);
		var response = isApproved
			? _securityService.ApproveAuthorizationRequest(request, resource, user, client, requestedScopes, out code)
			: _securityService.RejectAuthorizationRequest(request);
		
		if (Session[OAuth2TransientLoginSessionKey] != null && (bool)Session[OAuth2TransientLoginSessionKey])
		{
			LogoutUser(user.Username);
		}
		if (client.Callback != "Pin")
		{
			return response;
		}
		
		if (isApproved == true)
			
		{
			 string RandomString(int length)
			{
				const string valid = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
				StringBuilder res = new StringBuilder();
				using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
				{
					byte[] uintBuffer = new byte[sizeof(uint)];

					while (length-- > 0)
					{
						rng.GetBytes(uintBuffer);
						uint num = BitConverter.ToUInt32(uintBuffer, 0);
						res.Append(valid[(int)(num % (uint)valid.Length)]);
					}
				}

				return res.ToString();
			}

			AuthorizationPin authorizationPin;
			{
				AuthorizationPin pin = "Pin";
				authorizationPin =  code;
				expirationdate = (_timeContext.Now);

			}
			return View("Pin", model);
			

		}
		return response;
	}

Can you be more specific about the errors you are getting?

One place I can see potential problems is this:

string RandomString(int length)
	{
		const string valid = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
		StringBuilder res = new StringBuilder();
		using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
		{
			byte[] uintBuffer = new byte[sizeof(uint)];

			while (length-- > 0)
			{
				rng.GetBytes(uintBuffer);
				uint num = BitConverter.ToUInt32(uintBuffer, 0);
				res.Append(valid[(int)(num % (uint)valid.Length)]);
			}
		}

		return res.ToString();
	}

For one thing, your description asks for a 10-character Base64 string, but I don’t see where the length argument is ever supplied. The string valid is not representative of Base64, and is missing a few characters.

[Originally I said the string valid was never used, but I spotted it later]

Also, I’m a wee bit rusty on .NET stuff, but I’m fairly certain that the entire RandomString method is either in the wrong place, or is simply never called at all.

There are also problems with the AuthorizationPin block, particularly that first line inside the braces. I don’t think that line should be there at all, but it depends on what you want it to be.

I know there are things that need to be fixed. I’m just not sure how to fix them exactly. I guess what I’m trying to say is I don’t know what to do with the instructions presented.

Well, without access to the rest of the code or docs, this is just a best guess based on the instructions you were given. Please note that I’ve added some comments to explain things just a little bit, and also to question the expiration.

I hope this helps:

public ActionResult ProcessAuthorization(bool isApproved) {
	Resource resource;
	User user;
	Client client;
	HashSet<string> requestedScopes;
	object code;

	var request = _securityService.ParseAuthorizationRequest(out resource, out user, out client, out requestedScopes);
	var response = isApproved
	? _securityService.ApproveAuthorizationRequest(request, resource, user, client, requestedScopes, out code)
	: _securityService.RejectAuthorizationRequest(request);

	if (Session[OAuth2TransientLoginSessionKey] != null && (bool)Session[OAuth2TransientLoginSessionKey]) {
		LogoutUser(user.Username);
	}
	
	if (client.Callback != "Pin") {
		return response;
	}

	if (isApproved == true) {
		string pin;
		using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider()) {
			byte[] buffer = new byte[7]; // This forces the output to have 10 characters, followed by "=="
			rng.GetBytes(buffer);
			
			pin = Convert.ToBase64String(buffer).TrimEnd('=');
			/* 
				Because the pin is Base64, the actual output was 12 characters.
				I've chopped off the last two characters (which are always equal signs)
				because your requirements state 10 characters.
				
				If you ever need to do anything Base64 with the pin, you'll have to add
				the "==" to the end, or it won't convert properly.
			*/
		}

		AuthorizationPin authPin = new AuthorizationPin { 
			AccessCode = code,
			Pin = pin,
			ExpirationDate = _timeContext.Now // This is telling the authorization to expire now... is that what you want?
		};
		
		authPinRepo.Insert(authPin);
		
		PinModel model = new PinModel { IsApproved = isApproved, Pin = pin };
		
		return View("Pin", model);
	}
	
	return response;
}
1 Like

This is the original code for that method:

                [ResourceServerAuthenticate(Order = 1), HttpPost, ValidateAntiForgeryToken(Order = 2)]
	public ActionResult ProcessAuthorization(bool isApproved)
	{
		Resource resource;
		User user;
		Client client;
		HashSet<string> requestedScopes;

		var request = _securityService.ParseAuthorizationRequest(out resource, out user, out client, out requestedScopes);

		var response = isApproved
			? _securityService.ApproveAuthorizationRequest(request, resource, user, client, requestedScopes)
			: _securityService.RejectAuthorizationRequest(request);

		if (Session[OAuth2TransientLoginSessionKey] != null && (bool)Session[OAuth2TransientLoginSessionKey])
		{
			LogoutUser(user.Username);
		}

		return response;
	}

I need to modify this method with these instructions:

  1. If isApproved is true:
    a. Assign the response “code” parameter (see above) to a local var, say code.
    b. Generate a random 10-character pin value via Convert.ToBase64String(new System.Security.Cryptography.RNGCryptoServiceProvider().GetBytes(buffer)), and assign to a local var, say pin.
    c. Create a DateTime (using process described below) for the ExpirationDate
    d. Instantiate a AuthorizationPin with { AccessCode = code, Pin = pin, ExpirationDate = expirationDate }. Leave Id as 0. NHibernate will know to allow the database to generate the Id (assuming that the REST API mapping file is configured correctly. See other mapping files in REST API.)
    e. Call authPinRepo.Insert(authPin) to save the AuthorizationPin
    Instantiate a PinModel with { IsApproved = isApproved, Pin = pin }
    return View(“Pin”, model);

Hopefully this helps

Does that mean that what I gave you does not work?

I’m sorry, but I can’t do anything more without knowing more. The only thing I can tell that might not work would be the “code” of the response, which I cannot mess with since I don’t know exactly how your responses are formatted, or what code is expected.

If you are still having issues, you’ll have to tell us exactly what the problem is before we can try to figure it out.

No I’m not saying that I’m giving you the original code and then the instructions that are needed to modify it.

What more do you need? More code? More info? Both?

The code does seem to work until I get to this section

             	AuthorizationPin authPin = new AuthorizationPin
	{
		AccessCode = code,
		Pin = pin,
		ExpirationDate = _timeContext.Now // This is telling the authorization to expire now... is that what you want?
	};

        authPinRepo.Insert(authPin);

I get this error
The property or indexer ‘AuthorizationPin.AccessCode’ cannot be used in this context because the set accessor is inaccessible.

Same error for Pin and ExpirationDate.

Also get error:
‘object’ does not contain a definition for ‘Now’ and no extension method ‘Now’ accepting a first argument of type ‘object’ could be found (are you missing a using directive or an assembly reference?)

on ‘Insert’ for authPinRepo.Insert(authPin); line and same on ‘Now’ on _timecontext.Now line.

Ah, well it seems that wherever the AuthorizationPin type is declared, it doesn’t want us settings things from the outside. You may have to change that whole authPin block into an old-fashioned constructor, depending on what the AuthorizationPin type is defined as. In other words, the instructions given you were misleading about instantiating the AuthorizationPin. Find out how AuthorizationPin expects to be instantiated, then use that instead.

The 'object' does not contain a definition for 'Now' error is telling you that _timeContext is not a DateTime object. Replace _timeContext.Now with new DateTime().Now, and see if that works.

Of course, it still won’t work until we figure out how to instantiate AuthorizationPin properly.

I have AuthorizationPin class file that get/set properties, is this what you are talking about

public class AuthorizationPin
{
    protected AuthorizationPin();

    public virtual long Id { get; protected set; }
    public virtual string Pin { get; protected set; }
    public virtual string AccessCode { get; protected set; }
    public virtual string Callback { get; protected set; }
    public virtual string ExpirationDate { get; protected set; }
     }

If not then no I don’t have it instantiated. How would I do that?

Also get this error on under new AuthorizationPin line

       AuthorizationPin authPin = new AuthorizationPin

‘AuthorizationPin.AuthorizationPin()’ is inaccessible due to its protection.’

Does that mean the class file is protected?

All those “protected set” are saying that only the class itself, or its descendents are able to set those properties. I believe that the protected AuthorizationPin(); might be why we are having issues. That is basically saying that only the class and its descendants can access the constructor.

The fact that all of the properties are virtual tells me that this class is probably supposed to be abstract, and not intended to be used directly.

Are there any classes that inherit from AuthorizationPin? If so, we could instantiate one of those instead.

Otherwise, we’ll have to make some changes to that class, which I don’t think you should do without running it past a team lead or supervisor. We could also use reflection, but that gets messy, and is probably not what you want to do on a secure environment.

Also, it’s expected the date as a string, so that’s something we’ll have to address when we return to the original code.

I did change that Expiration date

               public virtual DateTime ExpirationDate { get; protected set; }

There are no classes that inherit from AuthorizationPin.

I would have left it as a string and modified the other method, because we don’t currently know what they do with that data. Changing it to a DateTime there might cascade to numerous other changes you have to make.

I changed that back to a string. Do you have any suggestions on modifying with those errors that I mentioned previously? What approach should I go to clean up those errors?

As I said before, you need to run changing that AuthorizationPin’s constructor to public by someone higher up. Once you’ve got the go ahead, simply change that protected to public. That will clear up all of the issues with the authPin block, except for the expiration date, which we’ll need to make a string instead of a date time.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.